@apifuse/provider-sdk 2.1.0-beta.0 → 2.1.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (213) hide show
  1. package/AUTHORING.md +218 -21
  2. package/CHANGELOG.md +54 -0
  3. package/README.md +147 -10
  4. package/SUBMISSION.md +87 -0
  5. package/bin/apifuse-check.ts +86 -4
  6. package/bin/apifuse-dev.ts +87 -13
  7. package/bin/apifuse-pack-check.ts +120 -0
  8. package/bin/apifuse-pack-smoke.ts +423 -0
  9. package/bin/apifuse-perf.ts +142 -49
  10. package/bin/apifuse-record.ts +182 -104
  11. package/bin/apifuse-submit-check.ts +2538 -0
  12. package/bin/apifuse.ts +1 -1
  13. package/dist/ceremonies/index.d.ts +41 -0
  14. package/dist/ceremonies/index.js +490 -0
  15. package/dist/choice-token.d.ts +24 -0
  16. package/dist/choice-token.js +74 -0
  17. package/dist/cli/commands.d.ts +10 -0
  18. package/dist/cli/commands.js +80 -0
  19. package/dist/cli/create.d.ts +47 -0
  20. package/dist/cli/create.js +762 -0
  21. package/dist/cli/templates/provider/.dockerignore.tpl +22 -0
  22. package/dist/cli/templates/provider/.gitignore.tpl +22 -0
  23. package/dist/cli/templates/provider/Dockerfile.tpl +7 -0
  24. package/dist/cli/templates/provider/README.md.tpl +160 -0
  25. package/dist/cli/templates/provider/dev.ts.tpl +5 -0
  26. package/dist/cli/templates/provider/domain/README.md.tpl +3 -0
  27. package/dist/cli/templates/provider/index.test.ts.tpl +13 -0
  28. package/dist/cli/templates/provider/index.ts.tpl +15 -0
  29. package/dist/cli/templates/provider/mappers/README.md.tpl +3 -0
  30. package/dist/cli/templates/provider/meta.ts.tpl +7 -0
  31. package/dist/cli/templates/provider/operations/index.ts.tpl +5 -0
  32. package/dist/cli/templates/provider/operations/ping.ts.tpl +24 -0
  33. package/dist/cli/templates/provider/schemas/ping.ts.tpl +24 -0
  34. package/dist/cli/templates/provider/start.ts.tpl +5 -0
  35. package/dist/cli/templates/provider/upstream/README.md.tpl +3 -0
  36. package/dist/config/loader.d.ts +107 -0
  37. package/dist/config/loader.js +935 -0
  38. package/dist/contract-json.d.ts +9 -0
  39. package/dist/contract-json.js +51 -0
  40. package/dist/contract-serialization.d.ts +4 -0
  41. package/dist/contract-serialization.js +78 -0
  42. package/dist/contract-types.d.ts +49 -0
  43. package/dist/contract-types.js +1 -0
  44. package/dist/contract.d.ts +6 -0
  45. package/dist/contract.js +155 -0
  46. package/dist/define.d.ts +97 -0
  47. package/dist/define.js +1320 -0
  48. package/dist/dev.d.ts +9 -0
  49. package/dist/dev.js +15 -0
  50. package/dist/errors.d.ts +59 -0
  51. package/dist/errors.js +97 -0
  52. package/dist/i18n/catalog.d.ts +29 -0
  53. package/dist/i18n/catalog.js +159 -0
  54. package/dist/i18n/index.d.ts +2 -0
  55. package/dist/i18n/index.js +2 -0
  56. package/dist/i18n/keys.d.ts +10 -0
  57. package/dist/i18n/keys.js +34 -0
  58. package/dist/index.d.ts +41 -0
  59. package/dist/index.js +37 -0
  60. package/dist/lint.d.ts +73 -0
  61. package/dist/lint.js +702 -0
  62. package/dist/observability.d.ts +5 -0
  63. package/dist/observability.js +39 -0
  64. package/dist/provider.d.ts +9 -0
  65. package/dist/provider.js +8 -0
  66. package/dist/public-schema-field-lint.d.ts +2 -0
  67. package/dist/public-schema-field-lint.js +158 -0
  68. package/dist/recipes/gov-api.d.ts +19 -0
  69. package/dist/recipes/gov-api.js +72 -0
  70. package/dist/recipes/rest-api.d.ts +21 -0
  71. package/dist/recipes/rest-api.js +115 -0
  72. package/dist/runtime/auth-flow.d.ts +14 -0
  73. package/dist/runtime/auth-flow.js +44 -0
  74. package/dist/runtime/browser.d.ts +25 -0
  75. package/dist/runtime/browser.js +1034 -0
  76. package/dist/runtime/cache.d.ts +10 -0
  77. package/dist/runtime/cache.js +372 -0
  78. package/dist/runtime/choice.d.ts +15 -0
  79. package/dist/runtime/choice.js +435 -0
  80. package/dist/runtime/credential.d.ts +8 -0
  81. package/dist/runtime/credential.js +61 -0
  82. package/dist/runtime/env.d.ts +2 -0
  83. package/dist/runtime/env.js +10 -0
  84. package/dist/runtime/executor.d.ts +16 -0
  85. package/dist/runtime/executor.js +51 -0
  86. package/dist/runtime/http.d.ts +8 -0
  87. package/dist/runtime/http.js +706 -0
  88. package/dist/runtime/insights.d.ts +9 -0
  89. package/dist/runtime/insights.js +324 -0
  90. package/dist/runtime/instrumentation.d.ts +8 -0
  91. package/dist/runtime/instrumentation.js +269 -0
  92. package/dist/runtime/key-derivation.d.ts +24 -0
  93. package/dist/runtime/key-derivation.js +73 -0
  94. package/dist/runtime/keyring.d.ts +25 -0
  95. package/dist/runtime/keyring.js +93 -0
  96. package/dist/runtime/namespace.d.ts +9 -0
  97. package/dist/runtime/namespace.js +19 -0
  98. package/dist/runtime/otlp.d.ts +39 -0
  99. package/dist/runtime/otlp.js +103 -0
  100. package/dist/runtime/perf.d.ts +12 -0
  101. package/dist/runtime/perf.js +52 -0
  102. package/dist/runtime/prevalidate.d.ts +12 -0
  103. package/dist/runtime/prevalidate.js +173 -0
  104. package/dist/runtime/provider.d.ts +2 -0
  105. package/dist/runtime/provider.js +11 -0
  106. package/dist/runtime/proxy-errors.d.ts +21 -0
  107. package/dist/runtime/proxy-errors.js +83 -0
  108. package/dist/runtime/proxy-telemetry.d.ts +8 -0
  109. package/dist/runtime/proxy-telemetry.js +174 -0
  110. package/dist/runtime/redis.d.ts +17 -0
  111. package/dist/runtime/redis.js +82 -0
  112. package/dist/runtime/request-options.d.ts +3 -0
  113. package/dist/runtime/request-options.js +42 -0
  114. package/dist/runtime/state.d.ts +17 -0
  115. package/dist/runtime/state.js +344 -0
  116. package/dist/runtime/stealth.d.ts +18 -0
  117. package/dist/runtime/stealth.js +834 -0
  118. package/dist/runtime/stt.d.ts +22 -0
  119. package/dist/runtime/stt.js +480 -0
  120. package/dist/runtime/trace.d.ts +26 -0
  121. package/dist/runtime/trace.js +142 -0
  122. package/dist/runtime/waterfall.d.ts +12 -0
  123. package/dist/runtime/waterfall.js +147 -0
  124. package/dist/schema.d.ts +74 -0
  125. package/dist/schema.js +243 -0
  126. package/dist/serve.d.ts +1 -0
  127. package/dist/serve.js +1 -0
  128. package/dist/server/index.d.ts +3 -0
  129. package/dist/server/index.js +2 -0
  130. package/dist/server/serve.d.ts +64 -0
  131. package/dist/server/serve.js +1110 -0
  132. package/dist/server/types.d.ts +136 -0
  133. package/dist/server/types.js +86 -0
  134. package/dist/stealth/profiles.d.ts +4 -0
  135. package/dist/stealth/profiles.js +259 -0
  136. package/dist/stream.d.ts +44 -0
  137. package/dist/stream.js +151 -0
  138. package/dist/testing/helpers.d.ts +23 -0
  139. package/dist/testing/helpers.js +95 -0
  140. package/dist/testing/index.d.ts +2 -0
  141. package/dist/testing/index.js +2 -0
  142. package/dist/testing/run.d.ts +34 -0
  143. package/dist/testing/run.js +303 -0
  144. package/dist/types.d.ts +1326 -0
  145. package/dist/types.js +61 -0
  146. package/dist/utils/date.d.ts +6 -0
  147. package/dist/utils/date.js +101 -0
  148. package/dist/utils/parse.d.ts +16 -0
  149. package/dist/utils/parse.js +51 -0
  150. package/dist/utils/text.d.ts +4 -0
  151. package/dist/utils/text.js +14 -0
  152. package/dist/utils/transform.d.ts +8 -0
  153. package/dist/utils/transform.js +48 -0
  154. package/package.json +57 -29
  155. package/src/ceremonies/index.ts +30 -3
  156. package/src/choice-token.ts +165 -0
  157. package/src/cli/commands.ts +34 -11
  158. package/src/cli/create.ts +214 -52
  159. package/src/cli/templates/provider/.dockerignore.tpl +22 -0
  160. package/src/cli/templates/provider/.gitignore.tpl +22 -0
  161. package/src/cli/templates/provider/README.md.tpl +134 -2
  162. package/src/cli/templates/provider/dev.ts.tpl +1 -1
  163. package/src/cli/templates/provider/domain/README.md.tpl +3 -0
  164. package/src/cli/templates/provider/index.ts.tpl +5 -44
  165. package/src/cli/templates/provider/mappers/README.md.tpl +3 -0
  166. package/src/cli/templates/provider/meta.ts.tpl +7 -0
  167. package/src/cli/templates/provider/operations/index.ts.tpl +5 -0
  168. package/src/cli/templates/provider/operations/ping.ts.tpl +24 -0
  169. package/src/cli/templates/provider/schemas/ping.ts.tpl +24 -0
  170. package/src/cli/templates/provider/start.ts.tpl +1 -1
  171. package/src/cli/templates/provider/upstream/README.md.tpl +3 -0
  172. package/src/config/loader.ts +1282 -7
  173. package/src/contract-json.ts +75 -0
  174. package/src/contract-serialization.ts +89 -0
  175. package/src/contract-types.ts +52 -0
  176. package/src/contract.ts +215 -0
  177. package/src/define.ts +1726 -48
  178. package/src/errors.ts +27 -0
  179. package/src/i18n/catalog.ts +277 -0
  180. package/src/i18n/index.ts +2 -0
  181. package/src/i18n/keys.ts +64 -0
  182. package/src/index.ts +174 -15
  183. package/src/lint.ts +547 -73
  184. package/src/observability.ts +41 -0
  185. package/src/provider.ts +104 -5
  186. package/src/public-schema-field-lint.ts +237 -0
  187. package/src/runtime/auth-flow.ts +7 -0
  188. package/src/runtime/browser.ts +762 -51
  189. package/src/runtime/cache.ts +528 -0
  190. package/src/runtime/choice.ts +760 -0
  191. package/src/runtime/executor.ts +32 -3
  192. package/src/runtime/http.ts +945 -185
  193. package/src/runtime/insights.ts +11 -11
  194. package/src/runtime/instrumentation.ts +12 -4
  195. package/src/runtime/key-derivation.ts +1 -1
  196. package/src/runtime/keyring.ts +4 -3
  197. package/src/runtime/proxy-errors.ts +132 -0
  198. package/src/runtime/proxy-telemetry.ts +253 -0
  199. package/src/runtime/redis.ts +116 -0
  200. package/src/runtime/request-options.ts +66 -0
  201. package/src/runtime/state.ts +563 -0
  202. package/src/runtime/stealth.ts +1159 -0
  203. package/src/runtime/stt.ts +629 -0
  204. package/src/runtime/trace.ts +1 -1
  205. package/src/schema.ts +363 -1
  206. package/src/server/serve.ts +1172 -76
  207. package/src/server/types.ts +37 -0
  208. package/src/stream.ts +210 -0
  209. package/src/testing/run.ts +31 -5
  210. package/src/types.ts +1118 -44
  211. package/src/composite.ts +0 -43
  212. package/src/runtime/tls.ts +0 -425
  213. package/src/types/playwright-stealth.d.ts +0 -9
package/src/types.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import type ms from "ms";
2
+
1
3
  import type { infer as ZodInfer, ZodType } from "zod";
2
4
 
3
5
  /** Minimal Standard Schema v1 shape accepted by provider operations. */
@@ -45,6 +47,51 @@ export interface OperationInputExample {
45
47
  rationale?: string;
46
48
  }
47
49
 
50
+ export type OperationRiskClass =
51
+ | "read"
52
+ | "write"
53
+ | "destructive"
54
+ | "external-send";
55
+
56
+ export type OperationApprovalPolicy = "never" | "risk-based" | "always";
57
+
58
+ export interface OperationToolRouterMetadata {
59
+ /** Optional MCP-safe override. Defaults to providerId__operationId. */
60
+ name?: string;
61
+ /** Safety class exposed to Tool Router clients and approval policy. */
62
+ riskClass?: OperationRiskClass;
63
+ /** OpenAI remote-MCP approval hint. Defaults from riskClass. */
64
+ approval?: OperationApprovalPolicy;
65
+ /** Override connection requirement when provider auth + openWorld inference is insufficient. */
66
+ requiresConnection?: boolean;
67
+ /** Public argument used to resolve the tenant-owned connection. Defaults to externalRef. */
68
+ connectionExternalRefParam?: string;
69
+ }
70
+
71
+ export type OperationSensitivePath = string;
72
+
73
+ export interface OperationObservabilitySensitiveConfig {
74
+ /**
75
+ * Additional dot paths to redact from captured invocation inputs. Use `*`
76
+ * for array elements, for example `items.*.phone`.
77
+ */
78
+ input?: readonly OperationSensitivePath[];
79
+ /**
80
+ * Additional dot paths to redact from captured invocation outputs. Use `*`
81
+ * for array elements, for example `items.*.paymentUrl`.
82
+ */
83
+ output?: readonly OperationSensitivePath[];
84
+ }
85
+
86
+ export interface OperationObservabilityConfig {
87
+ /**
88
+ * Complements schema-level `fields.*()` / `sensitive()` metadata for values
89
+ * that are shape-dependent, provider-normalized, or otherwise easier to
90
+ * express as stable public paths.
91
+ */
92
+ sensitive?: OperationObservabilitySensitiveConfig;
93
+ }
94
+
48
95
  export interface OperationAnnotations {
49
96
  readOnly?: boolean;
50
97
  destructive?: boolean;
@@ -80,9 +127,349 @@ export interface OperationAnnotations {
80
127
  export const OPERATION_TIMEOUT_MS_MIN = 1;
81
128
  export const OPERATION_TIMEOUT_MS_MAX = 60_000;
82
129
 
130
+ export const STREAM_HEARTBEAT_MS_MIN = 1_000;
131
+ export const STREAM_HEARTBEAT_MS_MAX = 60_000;
132
+ export const STREAM_IDLE_TIMEOUT_MS_MIN = 1_000;
133
+ export const STREAM_IDLE_TIMEOUT_MS_MAX = 300_000;
134
+ export const STREAM_MAX_DURATION_MS_MIN = 1_000;
135
+ export const STREAM_MAX_DURATION_MS_MAX = 1_800_000;
136
+ export const STREAM_CHUNK_BYTES_MIN = 1;
137
+ export const STREAM_CHUNK_BYTES_MAX = 1_048_576;
138
+
139
+ export type OperationTransportKind =
140
+ | "json"
141
+ | "sse"
142
+ | "http-stream"
143
+ | "websocket";
144
+
145
+ export interface OperationJsonTransport {
146
+ kind: "json";
147
+ }
148
+
149
+ export interface OperationSseTransport {
150
+ kind: "sse";
151
+ heartbeatMs?: number;
152
+ idleTimeoutMs?: number;
153
+ maxDurationMs?: number;
154
+ maxEventBytes?: number;
155
+ resumable?: false | "last-event-id";
156
+ events: Record<string, SchemaLike>;
157
+ }
158
+
159
+ export interface OperationHttpStreamTransport {
160
+ kind: "http-stream";
161
+ contentType?: string;
162
+ idleTimeoutMs?: number;
163
+ maxDurationMs?: number;
164
+ maxChunkBytes?: number;
165
+ }
166
+
167
+ export interface OperationWebSocketTransport {
168
+ kind: "websocket";
169
+ subprotocols?: readonly string[];
170
+ idleTimeoutMs?: number;
171
+ maxDurationMs?: number;
172
+ maxFrameBytes?: number;
173
+ /**
174
+ * WebSocket Operation metadata is future-ready. Gateway dispatch remains
175
+ * disabled until a gateway-managed session implementation is present.
176
+ */
177
+ dispatch: "unsupported";
178
+ }
179
+
180
+ export type OperationTransport =
181
+ | OperationJsonTransport
182
+ | OperationSseTransport
183
+ | OperationHttpStreamTransport
184
+ | OperationWebSocketTransport;
185
+
186
+ export const DEFAULT_OPERATION_TRANSPORT: OperationJsonTransport = {
187
+ kind: "json",
188
+ };
189
+
83
190
  export interface OperationRelationships {
84
191
  alternatives?: string[];
85
- chainsWith?: string[];
192
+ }
193
+
194
+ export type Iso3166Alpha2CountryCode = Uppercase<string>;
195
+ export type Bcp47Locale = string;
196
+ export type ProviderLocale = Bcp47Locale;
197
+ export type ProviderLocaleKey = string & {
198
+ readonly __brand: "ProviderLocaleKey";
199
+ };
200
+ export type ProviderLocaleKeyInput = ProviderLocaleKey | string;
201
+ export type Iso8601Duration = string;
202
+ export type Rfc3339Instant = string;
203
+ export type IanaTimeZone = string;
204
+ export type Iso4217CurrencyCode = Uppercase<string>;
205
+ export type E164PhoneNumber = `+${string}`;
206
+
207
+ export type SmsOrigin =
208
+ | {
209
+ /** Sender represented as an ITU-T E.164 phone number. */
210
+ kind: "e164";
211
+ value: E164PhoneNumber;
212
+ display?: string;
213
+ }
214
+ | {
215
+ /** Country-local service sender, for example KR 1661-5270. */
216
+ kind: "nationalServiceCode";
217
+ country: Iso3166Alpha2CountryCode;
218
+ value: string;
219
+ display?: string;
220
+ };
221
+
222
+ export interface SmsOtpExtractionPattern {
223
+ /** RegExp or source string containing exactly one usable OTP capture. */
224
+ pattern: RegExp | string;
225
+ /** Named capture key or one-based numeric capture index. Defaults to first capture. */
226
+ capture?: string | number;
227
+ }
228
+
229
+ export interface SmsOtpMatcherDefinition {
230
+ id: string;
231
+ country: Iso3166Alpha2CountryCode;
232
+ locale?: Bcp47Locale;
233
+ phoneNumber?: E164PhoneNumber;
234
+ origins: readonly [SmsOrigin, ...SmsOrigin[]];
235
+ code: SmsOtpExtractionPattern;
236
+ maxAge: Iso8601Duration;
237
+ waitTimeout: Iso8601Duration;
238
+ clockSkew?: Iso8601Duration;
239
+ /** Runtime/fixture helper. Not serialized into generated registry artifacts. */
240
+ extractOtp(body: string): string | null;
241
+ }
242
+
243
+ export type SttTranscribeMode = "general" | "otp";
244
+ export type SttPromptPolicy = "none" | "default-hint" | "custom-hint";
245
+ export type SttUnsupportedOptionPolicy = "warn" | "error";
246
+ export type ProviderSttMode = "optional" | "required";
247
+
248
+ export interface ProviderSttConfig {
249
+ mode: ProviderSttMode;
250
+ }
251
+
252
+ export type SttAudioInput = {
253
+ kind: "base64";
254
+ data: string;
255
+ mediaType?: string;
256
+ durationMs?: number;
257
+ };
258
+
259
+ export interface SttVerificationCodeOptions {
260
+ locale?: Bcp47Locale;
261
+ codeLengths?: number | readonly number[] | { min: number; max: number };
262
+ }
263
+
264
+ export interface SttTranscribeRequest {
265
+ audio: SttAudioInput;
266
+ language?: Bcp47Locale;
267
+ mode?: SttTranscribeMode;
268
+ promptPolicy?: SttPromptPolicy;
269
+ initialPrompt?: string;
270
+ unsupportedOptionPolicy?: SttUnsupportedOptionPolicy;
271
+ verificationCode?: SttVerificationCodeOptions;
272
+ timeoutMs?: number;
273
+ maxAudioBytes?: number;
274
+ }
275
+
276
+ export interface SttSegment {
277
+ text: string;
278
+ startMs?: number;
279
+ endMs?: number;
280
+ confidence?: number;
281
+ }
282
+
283
+ export interface SttUsage {
284
+ audioDurationMs?: number;
285
+ audioBytes?: number;
286
+ billableUnits?: number;
287
+ }
288
+
289
+ export interface SttWarning {
290
+ code: "UNSUPPORTED_STT_OPTION" | "PROMPT_IGNORED" | "LOCALE_PARTIAL";
291
+ message: string;
292
+ }
293
+
294
+ export interface SttTranscript {
295
+ text: string;
296
+ language?: Bcp47Locale;
297
+ durationMs?: number;
298
+ segments?: readonly SttSegment[];
299
+ usage?: SttUsage;
300
+ warnings?: readonly SttWarning[];
301
+ verificationCode?: VerificationCodeExtractionResult;
302
+ }
303
+
304
+ export type VerificationCodeCandidateSource =
305
+ | "digits"
306
+ | "spoken_words"
307
+ | "mixed";
308
+
309
+ export interface VerificationCodeCandidate {
310
+ code: string;
311
+ source: VerificationCodeCandidateSource;
312
+ startIndex?: number;
313
+ endIndex?: number;
314
+ }
315
+
316
+ export interface VerificationCodeExtractionResult {
317
+ code: string;
318
+ candidates: readonly VerificationCodeCandidate[];
319
+ normalizedText: string;
320
+ }
321
+
322
+ export interface SttContext {
323
+ transcribe(request: SttTranscribeRequest): Promise<SttTranscript>;
324
+ extractVerificationCode(
325
+ text: string,
326
+ options?: SttVerificationCodeOptions,
327
+ ): VerificationCodeExtractionResult;
328
+ }
329
+
330
+ export interface HealthJourneySchedule {
331
+ kind: "interval";
332
+ /** ISO 8601 duration, for example PT8H. */
333
+ interval: Iso8601Duration;
334
+ jitter?: Iso8601Duration;
335
+ }
336
+
337
+ export interface HealthJourneyStep {
338
+ id: string;
339
+ description?: string;
340
+ operationId?: string;
341
+ usesSmsMatcher?: string;
342
+ coversOperations?: readonly string[];
343
+ safeBoundary?: "paymentWebviewUrl" | "paymentUrl" | "none";
344
+ kind?: "operation" | "smsOtp" | "assertion" | "journal";
345
+ }
346
+
347
+ export interface HealthJourneyGatewayContext {
348
+ connect?(options?: {
349
+ providerId?: string;
350
+ externalRef?: string;
351
+ authMode?: "credentials" | "oauth2";
352
+ input?: Record<string, unknown>;
353
+ metadata?: Record<string, unknown>;
354
+ }): Promise<{ connectionId: string; rowVersion: number }>;
355
+ disconnect?(connection: {
356
+ connectionId: string;
357
+ rowVersion: number;
358
+ }): Promise<void>;
359
+ execute(
360
+ providerId: string,
361
+ operationId: string,
362
+ input: unknown,
363
+ options?: {
364
+ connectionId?: string;
365
+ requestId?: string;
366
+ /**
367
+ * Set false when the journey will record the semantic operation
368
+ * outcome itself through `ctx.event.operation()`. Transport success
369
+ * must not become a competing public health sample in that case.
370
+ */
371
+ recordOperationEvent?: boolean;
372
+ },
373
+ ): Promise<{
374
+ data: unknown;
375
+ status: number;
376
+ duration: number;
377
+ meta?: Record<string, unknown>;
378
+ }>;
379
+ }
380
+
381
+ export interface SmsPhoneIdentity {
382
+ id: string;
383
+ country: Iso3166Alpha2CountryCode | string;
384
+ e164: E164PhoneNumber | string;
385
+ nationalNumber: string;
386
+ displayName?: string;
387
+ }
388
+
389
+ export interface HealthJourneySmsContext {
390
+ resolvePhone(params?: { matcherId?: string }): Promise<SmsPhoneIdentity>;
391
+ waitForOtp(params: {
392
+ matcherId: string;
393
+ attemptId: string;
394
+ phoneId?: string;
395
+ phoneNumber?: string;
396
+ signal?: AbortSignal;
397
+ }): Promise<{ code: string; messageId: string; receivedAt: string }>;
398
+ }
399
+
400
+ export interface HealthJourneyJournalContext {
401
+ sideEffect<T>(params: {
402
+ stepId: string;
403
+ kind: string;
404
+ idempotencyKey: string;
405
+ run: () => Promise<T>;
406
+ }): Promise<T>;
407
+ }
408
+
409
+ export interface HealthJourneyEventContext {
410
+ /**
411
+ * Record an operation-level health outcome that was proven by the journey but
412
+ * not emitted by a direct `ctx.gateway.execute()` call, such as a recovery or
413
+ * manual-review assertion. This is intentionally narrow; it is not a generic
414
+ * event bus.
415
+ */
416
+ operation(params: {
417
+ operationId: string;
418
+ status: "ok" | "degraded" | "down" | "unknown" | "not_reached";
419
+ stepId?: string;
420
+ label?: string;
421
+ error?: string;
422
+ latencyMs?: number;
423
+ statusCode?: number;
424
+ metadata?: Record<string, unknown>;
425
+ }): Promise<void>;
426
+ }
427
+
428
+ export interface HealthJourneyRunContext {
429
+ attemptId: string;
430
+ providerId: string;
431
+ journeyId: string;
432
+ gateway: HealthJourneyGatewayContext;
433
+ sms: HealthJourneySmsContext;
434
+ journal: HealthJourneyJournalContext;
435
+ state: ProviderRuntimeState;
436
+ event: HealthJourneyEventContext;
437
+ signal: AbortSignal;
438
+ secrets: Record<string, string | undefined>;
439
+ }
440
+
441
+ export type HealthJourneyManualTriggerPolicy =
442
+ | { enabled: false; reason?: string }
443
+ | {
444
+ enabled: true;
445
+ requiresAcknowledgement: boolean;
446
+ risk: "read_only" | "writes_external_state" | "sms_or_payment";
447
+ /** ISO 8601 duration. Minimum time between manual executions. */
448
+ minManualInterval: Iso8601Duration;
449
+ publicRationale: string;
450
+ };
451
+
452
+ export interface HealthJourneyRunResult {
453
+ status?: "ok" | "degraded" | "down" | "unknown";
454
+ label?: string;
455
+ metadata?: Record<string, unknown>;
456
+ }
457
+
458
+ export interface HealthJourneyDefinition {
459
+ id: string;
460
+ title?: string;
461
+ description?: string;
462
+ schedule: HealthJourneySchedule;
463
+ coversOperations: readonly [string, ...string[]];
464
+ timeout?: Iso8601Duration;
465
+ cooldown?: Iso8601Duration;
466
+ smsMatchers?: readonly SmsOtpMatcherDefinition[];
467
+ requiredSecrets?: readonly string[];
468
+ manualTrigger?: HealthJourneyManualTriggerPolicy;
469
+ steps: readonly [HealthJourneyStep, ...HealthJourneyStep[]];
470
+ run?: (
471
+ ctx: HealthJourneyRunContext,
472
+ ) => Promise<HealthJourneyRunResult | undefined>;
86
473
  }
87
474
 
88
475
  /**
@@ -96,9 +483,14 @@ export interface OperationRelationships {
96
483
  * See `openspec/changes/enforce-sdk-operation-health-suite/design.md` §D1.
97
484
  */
98
485
 
99
- /** Polling intervals supported by the health-monitor runtime. */
100
- export type ProbeInterval = "30s" | "1m" | "3m" | "5m" | "15m" | "30m" | "1h";
486
+ /** Polling interval duration accepted by the health-monitor runtime. */
487
+ export type ProbeInterval = ms.StringValue;
101
488
 
489
+ /**
490
+ * Common probe interval examples retained for discoverability/backwards
491
+ * compatibility. This list is not exhaustive; any positive `ms`-style duration
492
+ * string accepted by `@types/ms` (for example `2m`, `8h`, or `1 day`) is valid.
493
+ */
102
494
  export const PROBE_INTERVALS: readonly ProbeInterval[] = [
103
495
  "30s",
104
496
  "1m",
@@ -107,8 +499,16 @@ export const PROBE_INTERVALS: readonly ProbeInterval[] = [
107
499
  "15m",
108
500
  "30m",
109
501
  "1h",
502
+ "2h",
503
+ "8h",
504
+ "24h",
110
505
  ] as const;
111
506
 
507
+ export const HEALTH_CHECK_TIMEOUT_MS_MIN = 1;
508
+ export const HEALTH_CHECK_TIMEOUT_MS_MAX = 60_000;
509
+ export const HEALTH_CHECK_DEGRADED_THRESHOLD_MS_MIN = 1;
510
+ export const HEALTH_CHECK_DEGRADED_THRESHOLD_MS_MAX = 60_000;
511
+
112
512
  /**
113
513
  * Context passed to a `HealthCheckCase.assertions` lambda.
114
514
  * `data` is typed against the operation's declared output schema (TOutput).
@@ -120,6 +520,28 @@ export interface HealthCheckAssertionContext<TOutput = unknown> {
120
520
  readonly status: number;
121
521
  /** Wall-clock duration of the operation invocation, in milliseconds. */
122
522
  readonly durationMs: number;
523
+ /** Optional provider response metadata such as cache hit/stale flags. */
524
+ readonly meta?: Record<string, unknown>;
525
+ }
526
+
527
+ export interface HealthCheckInputPreparationContext<TInput = unknown> {
528
+ readonly providerId: string;
529
+ readonly operationId: string;
530
+ readonly input: TInput;
531
+ readonly connectionId?: string;
532
+ readonly gateway: {
533
+ execute: (
534
+ providerId: string,
535
+ operationId: string,
536
+ input: unknown,
537
+ options?: { connectionId?: string },
538
+ ) => Promise<{
539
+ status: number;
540
+ duration: number;
541
+ data: unknown;
542
+ meta?: Record<string, unknown>;
543
+ }>;
544
+ };
123
545
  }
124
546
 
125
547
  /**
@@ -148,6 +570,14 @@ export interface HealthCheckCase<TInput = unknown, TOutput = unknown> {
148
570
  description?: string;
149
571
  /** Input passed to the operation handler for this case. */
150
572
  input: TInput;
573
+ /**
574
+ * Optional runtime input preparation hook for volatile probes. Use this when
575
+ * the durable probe input must be derived from a live read-only operation
576
+ * immediately before the checked operation executes.
577
+ */
578
+ prepareInput?: (
579
+ ctx: HealthCheckInputPreparationContext<TInput>,
580
+ ) => TInput | Promise<TInput>;
151
581
  /**
152
582
  * Assertion executed against the operation's response and timing.
153
583
  *
@@ -167,6 +597,8 @@ export interface HealthCheckCase<TInput = unknown, TOutput = unknown> {
167
597
  | Promise<HealthCheckCaseResult>;
168
598
  /** Override per-case degradation threshold (ms); falls back to the suite default. */
169
599
  degradedThresholdMs?: number;
600
+ /** Override per-case timeout in milliseconds; falls back to the suite/provider/runtime default. */
601
+ timeoutMs?: number;
170
602
  /** Expected outcome for "negative" cases (e.g., expecting a degraded baseline). Default: `"ok"`. */
171
603
  expectedStatus?: "ok" | "degraded";
172
604
  /** Runtime gate (env-driven); if returns false the case is skipped & logged. */
@@ -182,6 +614,8 @@ export interface HealthCheckSuite<TInput = unknown, TOutput = unknown> {
182
614
  interval: ProbeInterval;
183
615
  /** Per-case timeout in milliseconds. Default: 30000. */
184
616
  timeoutMs?: number;
617
+ /** Default degradation threshold for cases in this suite. Default: runtime threshold. */
618
+ degradedThresholdMs?: number;
185
619
  /** Non-empty list of cases. Empty arrays are rejected at definition time. */
186
620
  cases: [
187
621
  HealthCheckCase<TInput, TOutput>,
@@ -217,18 +651,51 @@ export interface HealthCheckUnsupported {
217
651
  */
218
652
  export interface ProviderHealthMonitorConfig {
219
653
  /**
220
- * Env-secret key names (e.g., "HEALTH_MONITOR_CATCHTABLE_PHONE") the
654
+ * Provider-wide default probe timeout in milliseconds. Individual
655
+ * `healthCheck.timeoutMs` and `healthCheck.cases[].timeoutMs` values take
656
+ * precedence. Defaults to the monitor runtime default.
657
+ */
658
+ defaultProbeTimeoutMs?: number;
659
+ /**
660
+ * Provider-wide default latency threshold in milliseconds before an
661
+ * otherwise successful probe is marked degraded. Suite/case thresholds take
662
+ * precedence. Defaults to the monitor runtime default.
663
+ */
664
+ defaultDegradedThresholdMs?: number;
665
+ /**
666
+ * Env-secret key names (e.g., "APIFUSE__HEALTH_MONITOR__CATCHTABLE_PHONE") the
221
667
  * synthetic-monitor runtime needs to execute probes that declare
222
668
  * `requiresConnection: true`.
223
669
  */
224
670
  requiredSecrets?: string[];
671
+ /**
672
+ * Mapping from provider auth ceremony input fields to runtime env-secret
673
+ * names. The health-monitor uses this to create a fresh connection for
674
+ * `requiresConnection: true` probes, then disconnects after execution.
675
+ */
676
+ credentialInputs?: Record<string, string>;
677
+ /**
678
+ * Runtime probe overrides keyed by generated registry probe id. Use this for
679
+ * operation health checks that need a runtime-specific interval or threshold
680
+ * without changing the provider-authored default suite.
681
+ */
682
+ probeOverrides?: Record<string, HealthMonitorProbeOverride>;
225
683
  /**
226
684
  * Override the default service account ID for this provider's probes.
227
- * Defaults to the runtime's `APIFUSE_SERVICE_ACCOUNT_ID` env var.
685
+ * Defaults to the runtime's `APIFUSE__HEALTH_MONITOR__SERVICE_ACCOUNT_ID` env var.
228
686
  */
229
687
  serviceAccount?: string;
230
688
  }
231
689
 
690
+ export interface HealthMonitorProbeOverride {
691
+ /** Optional runtime interval override as a positive `ms`-style duration string. */
692
+ interval?: ProbeInterval;
693
+ /** Optional timeout override for generated registry probes. */
694
+ timeoutMs?: number;
695
+ /** Optional degraded threshold override for generated registry probes. */
696
+ degradedThresholdMs?: number;
697
+ }
698
+
232
699
  export interface OperationErrorCode {
233
700
  code: string;
234
701
  status?: number;
@@ -237,10 +704,11 @@ export interface OperationErrorCode {
237
704
  }
238
705
 
239
706
  export interface OperationDocMeta {
240
- title?: string;
241
- description?: string;
242
- summary?: string;
243
- normalizationNotes?: string[];
707
+ titleKey?: ProviderLocaleKeyInput;
708
+ descriptionKey?: ProviderLocaleKeyInput;
709
+ summaryKey?: ProviderLocaleKeyInput;
710
+ markdownKey?: ProviderLocaleKeyInput;
711
+ normalizationNotesKeys?: ProviderLocaleKeyInput[];
244
712
  requestExample?: Record<string, unknown>;
245
713
  responseExample?: unknown;
246
714
  errorCodes?: OperationErrorCode[];
@@ -249,12 +717,12 @@ export interface OperationDocMeta {
249
717
  export type StealthPlatform = "macos" | "windows" | "linux" | "android" | "ios";
250
718
 
251
719
  export type BrowserEngine = "playwright-stealth" | "nodriver" | "selenium-uc";
252
-
253
720
  export interface BrowserOptions {
254
721
  headless?: boolean;
255
722
  stealth?: boolean;
256
723
  proxy?: string;
257
724
  engine?: BrowserEngine;
725
+ requireCdpPool?: boolean;
258
726
  }
259
727
 
260
728
  export interface StealthProfile {
@@ -275,36 +743,259 @@ export type ConnectionMode = AuthMode;
275
743
 
276
744
  export type ProviderReviewed = "first-party" | "community" | "staging";
277
745
 
746
+ export type ProviderAccessVisibility = "public" | "early_access";
747
+
748
+ export type ProviderProxyMode = "disabled" | "optional" | "required";
749
+
750
+ export type ProviderProxyProvider = "smartproxy" | "decodo" | "custom";
751
+
752
+ export type ProviderProxySessionAffinity =
753
+ | "request"
754
+ | "operation"
755
+ | "auth-flow"
756
+ | "connection";
757
+
758
+ export interface ProviderProxyPolicy {
759
+ /**
760
+ * Provider intent only. Transport details such as raw CONNECT, origin
761
+ * certificate verification, and vendor allocator endpoints are SDK-owned.
762
+ */
763
+ mode: ProviderProxyMode;
764
+ provider?: ProviderProxyProvider;
765
+ geo?: {
766
+ /** ISO 3166-1 alpha-2 country code, for example KR or US. */
767
+ country?: Iso3166Alpha2CountryCode;
768
+ subdivision?: string;
769
+ city?: string;
770
+ };
771
+ session?: {
772
+ affinity?: ProviderProxySessionAffinity;
773
+ lifetimeMinutes?: number;
774
+ poolSize?: number;
775
+ };
776
+ }
777
+
778
+ export type ProviderProxyConfig = boolean | ProviderProxyPolicy;
779
+
780
+ export interface ProviderAccessConfig {
781
+ /**
782
+ * Provider-level rollout visibility.
783
+ *
784
+ * - `public`: visible in public docs/catalog/OpenAPI and callable through
785
+ * the existing provider policy stack.
786
+ * - `early_access`: hidden from public discovery and callable only when the
787
+ * active customer organization has a provider-level access grant.
788
+ *
789
+ * This is intentionally provider-level only. It does not alter auth mode,
790
+ * operation schemas, health-check authoring, `openWorld`, or Connection
791
+ * requirements.
792
+ */
793
+ visibility?: ProviderAccessVisibility;
794
+ }
795
+
796
+ export type ProviderLogoSource = "asset" | "monogram" | "none";
797
+
798
+ export type ProviderLogoProfile =
799
+ | {
800
+ source: "asset";
801
+ path: string;
802
+ /**
803
+ * Absolute, customer-renderable URL emitted by discovery projections.
804
+ * Provider source definitions may omit this and let the registry projection
805
+ * derive it from the committed public asset path.
806
+ */
807
+ url?: string;
808
+ background?: string;
809
+ }
810
+ | {
811
+ source: "monogram" | "none";
812
+ background?: string;
813
+ fallbackReason: string;
814
+ };
815
+
816
+ export type ProviderPublicConnectionMode =
817
+ | "apifuse_managed"
818
+ | "workspace_enabled"
819
+ | "user_connected"
820
+ | "no_connection_required";
821
+
822
+ export type ProviderSupportLevel = "stable" | "beta" | "experimental";
823
+
824
+ export interface ProviderPublicProfile {
825
+ displayNameKey?: ProviderLocaleKeyInput;
826
+ shortDescriptionKey?: ProviderLocaleKeyInput;
827
+ longDescriptionKey?: ProviderLocaleKeyInput;
828
+ logo?: ProviderLogoProfile;
829
+ category?: string;
830
+ tags?: readonly string[];
831
+ capabilityKeys?: readonly ProviderLocaleKeyInput[];
832
+ examplePromptKeys?: readonly ProviderLocaleKeyInput[];
833
+ setupSummaryKey?: ProviderLocaleKeyInput;
834
+ connectionMode?: ProviderPublicConnectionMode;
835
+ requirementKeys?: readonly ProviderLocaleKeyInput[];
836
+ limitationKeys?: readonly ProviderLocaleKeyInput[];
837
+ availability?: {
838
+ regions?: readonly string[];
839
+ supportLevel?: ProviderSupportLevel;
840
+ };
841
+ /**
842
+ * Brand primary color as a 6-digit hex string (e.g. "#1a73e8").
843
+ * Single source of truth for all provider-specific color expressions
844
+ * (mood wash, monogram fallback, icon tint). The UI derives subtle washes
845
+ * via color-mix; provider definitions do not control mood percentages.
846
+ */
847
+ primaryColor?: string;
848
+ }
849
+
278
850
  export interface ProviderMeta {
279
851
  displayName: string;
280
- description?: string;
852
+ displayNameKey?: ProviderLocaleKeyInput;
853
+ descriptionKey: ProviderLocaleKeyInput;
281
854
  category: string;
282
- tags?: string[];
855
+ tags?: readonly string[];
283
856
  icon?: string;
284
- docTitle?: string;
285
- docDescription?: string;
286
- docSummary?: string;
287
- normalizationNotes?: string[];
857
+ docTitleKey?: ProviderLocaleKeyInput;
858
+ docDescriptionKey?: ProviderLocaleKeyInput;
859
+ docSummaryKey?: ProviderLocaleKeyInput;
860
+ docMarkdownKey?: ProviderLocaleKeyInput;
861
+ normalizationNotesKeys?: readonly ProviderLocaleKeyInput[];
288
862
  environment?: "staging";
289
863
  purpose?: string;
864
+ purposeKey?: ProviderLocaleKeyInput;
865
+ publicProfile?: ProviderPublicProfile;
866
+ contract?: {
867
+ publicSchemaFieldNames?: "normalized";
868
+ };
869
+ }
870
+
871
+ export type RequestParamPrimitive =
872
+ | string
873
+ | number
874
+ | boolean
875
+ | null
876
+ | undefined;
877
+ export type RequestParamValue =
878
+ | RequestParamPrimitive
879
+ | readonly RequestParamPrimitive[];
880
+ export type RequestParams = Record<string, RequestParamValue>;
881
+
882
+ export const HttpRetryPreset = {
883
+ Off: "off",
884
+ TransportTransient: "transport_transient",
885
+ SafeRead: "safe_read",
886
+ AggressiveRead: "aggressive_read",
887
+ RateLimitAware: "rate_limit_aware",
888
+ } as const;
889
+ export type HttpRetryPreset =
890
+ (typeof HttpRetryPreset)[keyof typeof HttpRetryPreset];
891
+
892
+ export const HttpRetryJitter = {
893
+ None: "none",
894
+ Full: "full",
895
+ Equal: "equal",
896
+ } as const;
897
+ export type HttpRetryJitter =
898
+ (typeof HttpRetryJitter)[keyof typeof HttpRetryJitter];
899
+
900
+ export const HttpRetryDelayStrategy = {
901
+ Fixed: "fixed",
902
+ Exponential: "exponential",
903
+ } as const;
904
+ export type HttpRetryDelayStrategy =
905
+ (typeof HttpRetryDelayStrategy)[keyof typeof HttpRetryDelayStrategy];
906
+
907
+ export const HttpRetryAfterPolicy = {
908
+ Ignore: "ignore",
909
+ /** Honor Retry-After up to maxDelayMs. */
910
+ Respect: "respect",
911
+ /** Honor Retry-After but also cap it to the SDK-computed backoff delay. */
912
+ Cap: "cap",
913
+ } as const;
914
+ export type HttpRetryAfterPolicy =
915
+ (typeof HttpRetryAfterPolicy)[keyof typeof HttpRetryAfterPolicy];
916
+
917
+ export const HttpRetryUnsafeMethodPolicy = {
918
+ Reject: "reject",
919
+ AllowExplicitUnsafe: "allow_explicit_unsafe",
920
+ } as const;
921
+ export type HttpRetryUnsafeMethodPolicy =
922
+ (typeof HttpRetryUnsafeMethodPolicy)[keyof typeof HttpRetryUnsafeMethodPolicy];
923
+
924
+ export interface HttpRetryOptions {
925
+ preset?: HttpRetryPreset;
926
+ /** Total logical ctx.http attempts, including the first attempt. */
927
+ attempts?: number;
928
+ methods?: readonly HttpMethod[];
929
+ statusCodes?: readonly number[];
930
+ errorCodes?: readonly string[];
931
+ delayStrategy?: HttpRetryDelayStrategy;
932
+ baseDelayMs?: number;
933
+ maxDelayMs?: number;
934
+ jitter?: HttpRetryJitter;
935
+ retryAfter?: HttpRetryAfterPolicy;
936
+ unsafeMethodPolicy?: HttpRetryUnsafeMethodPolicy;
937
+ }
938
+
939
+ export interface HttpRetrySummary {
940
+ attempts: number;
941
+ retries: number;
942
+ preset?: HttpRetryPreset;
943
+ transport: "native";
944
+ lastErrorCode?: string;
945
+ lastStatus?: number;
290
946
  }
291
947
 
292
948
  export interface RequestOptions {
293
949
  headers?: Record<string, string>;
294
- params?: Record<string, string>;
950
+ params?: RequestParams;
295
951
  proxy?: string;
296
952
  timeout?: number;
953
+ /**
954
+ * Defaults to true. Set to false when callers need to inspect upstream
955
+ * non-2xx bodies themselves instead of converting them to TransportError.
956
+ */
957
+ throwOnHttpError?: boolean;
958
+ retry?: boolean | HttpRetryPreset | HttpRetryOptions;
297
959
  }
298
960
 
299
- export interface TlsFetchOptions extends RequestOptions {
300
- method?: string;
961
+ export type HttpMethod =
962
+ | "HEAD"
963
+ | "head"
964
+ | "GET"
965
+ | "get"
966
+ | "POST"
967
+ | "post"
968
+ | "PUT"
969
+ | "put"
970
+ | "DELETE"
971
+ | "delete"
972
+ | "OPTIONS"
973
+ | "options"
974
+ | "TRACE"
975
+ | "trace"
976
+ | "PATCH"
977
+ | "patch";
978
+
979
+ export interface StealthFetchOptions extends RequestOptions {
980
+ method?: HttpMethod;
301
981
  body?: string | Buffer;
982
+ /**
983
+ * Offsets policy-managed proxy pool selection for caller-managed retries.
984
+ * Use when a request receives an upstream challenge page rather than a
985
+ * transport error, so the next logical retry does not restart at the same
986
+ * operation-affinity proxy.
987
+ */
988
+ proxyAttemptOffset?: number;
989
+ /** Override the configured browser-like stealth profile for this request. */
302
990
  profile?: string;
303
- tls?: {
304
- ja3?: string;
305
- h2?: Record<string, unknown>;
991
+ /**
992
+ * Stealth transport certificate controls. Use only for proxy products that
993
+ * terminate CONNECT with a private CA instead of tunneling the origin
994
+ * certificate chain.
995
+ */
996
+ stealth?: {
997
+ insecureSkipVerify?: boolean;
306
998
  };
307
- headerOrder?: string[];
308
999
  }
309
1000
 
310
1001
  export interface CookieJar {
@@ -314,7 +1005,7 @@ export interface CookieJar {
314
1005
  find?(predicate: (cookie: string) => boolean): string | undefined;
315
1006
  }
316
1007
 
317
- export interface DeclarativeTlsResponse {
1008
+ export interface DeclarativeStealthResponse {
318
1009
  status: number;
319
1010
  ok: boolean;
320
1011
  headers: Record<string, string>;
@@ -324,16 +1015,19 @@ export interface DeclarativeTlsResponse {
324
1015
  tlsInfo?: { protocol?: string; cipher?: string; [key: string]: unknown };
325
1016
  cookies: CookieJar;
326
1017
  json<T>(): Promise<T>;
1018
+ arrayBuffer(): Promise<ArrayBuffer>;
1019
+ bytes(): Promise<Uint8Array>;
327
1020
  }
328
1021
 
329
- export type TlsResponse = DeclarativeTlsResponse;
1022
+ export type StealthResponse = DeclarativeStealthResponse;
330
1023
 
331
1024
  export type RequestWithMethodOptions = RequestOptions & {
332
1025
  method?: string;
1026
+ body?: unknown;
333
1027
  };
334
1028
 
335
- export interface TlsSession {
336
- fetch(url: string, options?: TlsFetchOptions): Promise<TlsResponse>;
1029
+ export interface StealthSession {
1030
+ fetch(url: string, options?: StealthFetchOptions): Promise<StealthResponse>;
337
1031
  close(): void;
338
1032
  }
339
1033
 
@@ -343,6 +1037,9 @@ export interface ApiFuseResponse<T> {
343
1037
  requestId: string;
344
1038
  duration: number;
345
1039
  cached?: boolean;
1040
+ stale?: boolean;
1041
+ cache?: ProviderCacheResponseMeta;
1042
+ retry?: HttpRetrySummary;
346
1043
  };
347
1044
  }
348
1045
 
@@ -355,6 +1052,37 @@ export interface HttpResponse<T = unknown> {
355
1052
  text(): Promise<string>;
356
1053
  }
357
1054
 
1055
+ export interface HttpStreamResponse {
1056
+ status: number;
1057
+ ok: boolean;
1058
+ headers: Record<string, string>;
1059
+ body: ReadableStream<Uint8Array>;
1060
+ bytes(): AsyncIterable<Uint8Array>;
1061
+ textChunks(): AsyncIterable<string>;
1062
+ lines(): AsyncIterable<string>;
1063
+ }
1064
+
1065
+ export interface SseMessage {
1066
+ event: string;
1067
+ data: string;
1068
+ id?: string;
1069
+ retry?: number;
1070
+ json<T = unknown>(): T;
1071
+ }
1072
+
1073
+ export interface ProviderStreamEvent<TData = unknown> {
1074
+ event: string;
1075
+ data: TData;
1076
+ id?: string;
1077
+ retry?: number;
1078
+ }
1079
+
1080
+ export type OperationHandlerResult<TOutput> =
1081
+ | TOutput
1082
+ | Response
1083
+ | ReadableStream<Uint8Array>
1084
+ | AsyncIterable<ProviderStreamEvent>;
1085
+
358
1086
  export interface HttpClient {
359
1087
  request(url: string, opts?: RequestWithMethodOptions): Promise<HttpResponse>;
360
1088
  get(url: string, options?: RequestOptions): Promise<HttpResponse>;
@@ -369,18 +1097,142 @@ export interface HttpClient {
369
1097
  options?: RequestOptions,
370
1098
  ): Promise<HttpResponse>;
371
1099
  delete(url: string, options?: RequestOptions): Promise<HttpResponse>;
1100
+ stream(
1101
+ url: string,
1102
+ options?: RequestWithMethodOptions,
1103
+ ): Promise<HttpStreamResponse>;
1104
+ sse(
1105
+ url: string,
1106
+ options?: RequestWithMethodOptions,
1107
+ ): Promise<AsyncIterable<SseMessage>>;
372
1108
  }
373
1109
 
374
- export interface TlsClient {
375
- fetch(url: string, options?: TlsFetchOptions): Promise<TlsResponse>;
376
- createSession(opts?: { profile?: string }): TlsSession;
1110
+ export interface ProviderCacheKeyOptions {
1111
+ /**
1112
+ * Additional field names to omit from stable key material. The SDK always
1113
+ * omits known secret-bearing names such as serviceKey, authorization,
1114
+ * cookie, token, password, and secret.
1115
+ */
1116
+ redactFields?: string[];
1117
+ }
1118
+
1119
+ export interface ProviderCacheGetOrSetOptions {
1120
+ /** Freshness TTL. A fresh hit returns without calling the loader. */
1121
+ ttlMs: number;
1122
+ /**
1123
+ * Optional stale window after ttlMs. If the loader fails while the entry is
1124
+ * still inside this window, stale data is returned and marked stale.
1125
+ */
1126
+ staleIfErrorMs?: number;
1127
+ /** Optional jitter applied to writes to avoid synchronized expiry. */
1128
+ jitterPct?: number;
1129
+ }
1130
+
1131
+ export interface ProviderCacheLookupMeta {
1132
+ key: string;
1133
+ hit: boolean;
1134
+ stale: boolean;
1135
+ ageMs?: number;
1136
+ source: "redis" | "memory" | "loader";
1137
+ }
1138
+
1139
+ export interface ProviderCacheResult<T> {
1140
+ value: T;
1141
+ meta: ProviderCacheLookupMeta;
1142
+ }
1143
+
1144
+ export interface ProviderCacheResponseMeta {
1145
+ hit: boolean;
1146
+ stale: boolean;
1147
+ keys: string[];
1148
+ source?: "redis" | "memory" | "loader" | "mixed";
1149
+ }
1150
+
1151
+ export interface ProviderCache {
1152
+ key(
1153
+ namespace: string,
1154
+ parts: unknown,
1155
+ options?: ProviderCacheKeyOptions,
1156
+ ): string;
1157
+ get<T = unknown>(key: string): Promise<ProviderCacheResult<T> | null>;
1158
+ set<T = unknown>(
1159
+ key: string,
1160
+ value: T,
1161
+ options: ProviderCacheGetOrSetOptions,
1162
+ ): Promise<void>;
1163
+ delete(key: string): Promise<void>;
1164
+ getOrSet<T = unknown>(
1165
+ key: string,
1166
+ loader: () => Promise<T>,
1167
+ options: ProviderCacheGetOrSetOptions,
1168
+ ): Promise<ProviderCacheResult<T>>;
1169
+ responseMeta(): ProviderCacheResponseMeta | undefined;
1170
+ }
1171
+
1172
+ export interface StealthClient {
1173
+ fetch(url: string, options?: StealthFetchOptions): Promise<StealthResponse>;
1174
+ createSession(opts?: { profile?: string }): StealthSession;
1175
+ close?(): void;
377
1176
  }
378
1177
 
379
1178
  export interface BrowserClient {
380
1179
  readonly engine: BrowserEngine;
381
- newPage(): Promise<unknown>;
1180
+ close?(): Promise<void>;
1181
+ newPage(): Promise<BrowserPage>;
1182
+ rawPage(): Promise<BrowserPage>;
1183
+ withIsolatedContext<T>(
1184
+ handler: (page: BrowserPage) => Promise<T>,
1185
+ ): Promise<T>;
1186
+ solveChallenge(
1187
+ request: BrowserChallengeRequest,
1188
+ ): Promise<BrowserChallengeResult>;
1189
+ }
1190
+
1191
+ export interface BrowserLocator {
1192
+ click(): Promise<void>;
1193
+ fill(text: string): Promise<void>;
1194
+ textContent(): Promise<string | null>;
1195
+ waitFor(options?: { timeout?: number }): Promise<void>;
382
1196
  }
383
1197
 
1198
+ export interface BrowserFrame {
1199
+ id: string;
1200
+ name?: string;
1201
+ parentId?: string;
1202
+ url(): Promise<string>;
1203
+ title(): Promise<string>;
1204
+ content(): Promise<string>;
1205
+ evaluate<T>(fn: string | (() => T)): Promise<T>;
1206
+ locator(selector: string): BrowserLocator;
1207
+ }
1208
+
1209
+ export interface BrowserPage extends BrowserFrame {
1210
+ close(): Promise<void>;
1211
+ fill(selector: string, text: string): Promise<void>;
1212
+ goto(url: string): Promise<void>;
1213
+ pageId?: string;
1214
+ screenshot(options?: { fullPage?: boolean }): Promise<Buffer>;
1215
+ click(selector: string): Promise<void>;
1216
+ type(selector: string, text: string): Promise<void>;
1217
+ waitForSelector(
1218
+ selector: string,
1219
+ options?: { timeout?: number },
1220
+ ): Promise<void>;
1221
+ frames(): Promise<BrowserFrame[]>;
1222
+ }
1223
+
1224
+ export type BrowserChallengeRequest = {
1225
+ type: "recaptcha";
1226
+ siteKey?: string;
1227
+ timeout?: number;
1228
+ };
1229
+
1230
+ export type BrowserChallengeResult = {
1231
+ type: BrowserChallengeRequest["type"];
1232
+ solved: boolean;
1233
+ frameUrl?: string;
1234
+ };
1235
+
384
1236
  export type TraceAttributeValue = string | number | boolean;
385
1237
 
386
1238
  export interface TraceSpan {
@@ -436,6 +1288,107 @@ export interface ProviderRequestContext {
436
1288
  headers: Record<string, string>;
437
1289
  }
438
1290
 
1291
+ export interface ProviderChoiceBindingOptions {
1292
+ connection?: boolean;
1293
+ credentialKeys?: readonly string[];
1294
+ }
1295
+
1296
+ export type ProviderChoiceStorageOptions =
1297
+ | {
1298
+ readonly mode: "inline";
1299
+ }
1300
+ | {
1301
+ readonly mode: "server";
1302
+ readonly namespace: string;
1303
+ readonly state?: ProviderRuntimeState;
1304
+ readonly ttl?: ProviderStateDurationString;
1305
+ readonly maxEntries: number;
1306
+ readonly maxValueBytes: number;
1307
+ readonly unavailable?: "reject";
1308
+ }
1309
+ | {
1310
+ readonly mode: "auto";
1311
+ readonly namespace: string;
1312
+ readonly state?: ProviderRuntimeState;
1313
+ readonly ttl?: ProviderStateDurationString;
1314
+ readonly maxInlineBytes: number;
1315
+ readonly maxEntries: number;
1316
+ readonly maxValueBytes: number;
1317
+ readonly unavailable?: "reject";
1318
+ };
1319
+
1320
+ export interface ProviderChoiceIssueOptions<
1321
+ TPayload extends Record<string, unknown>,
1322
+ > {
1323
+ prefix: string;
1324
+ purpose: string;
1325
+ payload: TPayload;
1326
+ ttlMs: number;
1327
+ nowMs?: number;
1328
+ bind?: ProviderChoiceBindingOptions;
1329
+ storage?: ProviderChoiceStorageOptions;
1330
+ }
1331
+
1332
+ export interface ProviderChoiceParseOptions {
1333
+ token: string;
1334
+ prefix: string;
1335
+ purpose: string;
1336
+ ttlMs?: number;
1337
+ nowMs?: number;
1338
+ futureToleranceMs?: number;
1339
+ bind?: ProviderChoiceBindingOptions;
1340
+ storage?: ProviderChoiceStorageOptions;
1341
+ }
1342
+
1343
+ export interface ProviderChoiceContext {
1344
+ issue<TPayload extends Record<string, unknown>>(
1345
+ options: ProviderChoiceIssueOptions<TPayload> & {
1346
+ readonly storage?: { readonly mode: "inline" };
1347
+ },
1348
+ ): string;
1349
+ issue<TPayload extends Record<string, unknown>>(
1350
+ options: ProviderChoiceIssueOptions<TPayload> & {
1351
+ readonly storage: Extract<
1352
+ ProviderChoiceStorageOptions,
1353
+ { readonly mode: "server" }
1354
+ >;
1355
+ },
1356
+ ): Promise<string>;
1357
+ issue<TPayload extends Record<string, unknown>>(
1358
+ options: ProviderChoiceIssueOptions<TPayload> & {
1359
+ readonly storage: Extract<
1360
+ ProviderChoiceStorageOptions,
1361
+ { readonly mode: "auto" }
1362
+ >;
1363
+ },
1364
+ ): string | Promise<string>;
1365
+ issue<TPayload extends Record<string, unknown>>(
1366
+ options: ProviderChoiceIssueOptions<TPayload>,
1367
+ ): string | Promise<string>;
1368
+ parse(
1369
+ options: ProviderChoiceParseOptions & {
1370
+ readonly storage?: { readonly mode: "inline" };
1371
+ },
1372
+ ): Record<string, unknown>;
1373
+ parse(
1374
+ options: ProviderChoiceParseOptions & {
1375
+ readonly storage: Extract<
1376
+ ProviderChoiceStorageOptions,
1377
+ { readonly mode: "server" }
1378
+ >;
1379
+ },
1380
+ ): Promise<Record<string, unknown>>;
1381
+ parse(
1382
+ options: ProviderChoiceParseOptions & {
1383
+ readonly storage: Extract<
1384
+ ProviderChoiceStorageOptions,
1385
+ { readonly mode: "auto" }
1386
+ >;
1387
+ },
1388
+ ): Record<string, unknown> | Promise<Record<string, unknown>>;
1389
+ parse(options: ProviderChoiceParseOptions): Record<string, unknown>;
1390
+ }
1391
+
439
1392
  export interface ContextScratchpad {
440
1393
  get(key: string): unknown;
441
1394
  set(key: string, value: unknown): void;
@@ -450,8 +1403,11 @@ export interface FlowContext {
450
1403
  tenantId: string;
451
1404
  providerId: string;
452
1405
  http: HttpClient;
1406
+ stealth: StealthClient;
453
1407
  env: EnvContext;
1408
+ credential?: CredentialContext;
454
1409
  context: ContextScratchpad;
1410
+ stt: SttContext;
455
1411
  }
456
1412
 
457
1413
  export interface AuthTurn {
@@ -460,23 +1416,104 @@ export interface AuthTurn {
460
1416
  expiresAt?: string;
461
1417
  data?: Record<string, unknown>;
462
1418
  expectedInput?: Record<string, unknown>;
1419
+ /**
1420
+ * @deprecated Compatibility-only materialized provider auth hint.
1421
+ * Provider source must emit hintKey; SDK/server boundaries may materialize
1422
+ * this field from provider locale catalogs for legacy clients.
1423
+ */
463
1424
  hint?: string;
1425
+ /** Provider locale catalog key for the auth turn hint. */
1426
+ hintKey?: ProviderLocaleKeyInput;
464
1427
  timing?: {
465
1428
  suggestedPollIntervalMs?: number;
466
1429
  maxWaitMs?: number;
467
1430
  };
468
1431
  }
469
1432
 
470
- export type AuthFlowHandler = (
1433
+ export type AuthFlowStartHandler = (ctx: FlowContext) => Promise<AuthTurn>;
1434
+
1435
+ export type AuthFlowInputHandler = (
471
1436
  ctx: FlowContext,
472
1437
  input?: Record<string, unknown>,
473
1438
  ) => Promise<AuthTurn>;
474
1439
 
475
1440
  export interface AuthFlowDefinition {
476
- start: AuthFlowHandler;
477
- continue: AuthFlowHandler;
478
- poll?: AuthFlowHandler;
479
- abort?: AuthFlowHandler;
1441
+ start: AuthFlowStartHandler;
1442
+ continue: AuthFlowInputHandler;
1443
+ poll?: AuthFlowStartHandler;
1444
+ abort?: AuthFlowStartHandler;
1445
+ refresh?: AuthFlowInputHandler;
1446
+ }
1447
+
1448
+ export type ProviderStateDurationString =
1449
+ | `${number}${"ms" | "s" | "m" | "h" | "d"}`
1450
+ | `PT${string}`;
1451
+
1452
+ export interface StateNamespaceOptions {
1453
+ /** Default TTL used when a write omits ttl. Required to avoid unbounded state. */
1454
+ defaultTtl: ProviderStateDurationString;
1455
+ /** Maximum allowed TTL; writes are rejected when they exceed this policy. */
1456
+ maxTtl: ProviderStateDurationString;
1457
+ /** Maximum number of live entries in this namespace scope. */
1458
+ maxEntries: number;
1459
+ /** Maximum JSON-encoded value size in bytes. */
1460
+ maxValueBytes: number;
1461
+ }
1462
+
1463
+ export interface StateWriteOptions {
1464
+ ttl?: ProviderStateDurationString;
1465
+ }
1466
+
1467
+ export interface StateValue<T = unknown> {
1468
+ key: string;
1469
+ value: T;
1470
+ version: number;
1471
+ expiresAt: string;
1472
+ createdAt: string;
1473
+ updatedAt: string;
1474
+ }
1475
+
1476
+ export type StateCasResult<T = unknown> =
1477
+ | { ok: true; value: StateValue<T> }
1478
+ | { ok: false; current: StateValue<T> | null };
1479
+
1480
+ export interface ProviderStateNamespace {
1481
+ list<T = unknown>(options?: {
1482
+ limit?: number;
1483
+ /** Optional literal key prefix used for scoped recovery scans. */
1484
+ prefix?: string;
1485
+ }): Promise<StateValue<T>[]>;
1486
+ get<T = unknown>(key: string): Promise<StateValue<T> | null>;
1487
+ set<T = unknown>(
1488
+ key: string,
1489
+ value: T,
1490
+ options?: StateWriteOptions,
1491
+ ): Promise<StateValue<T>>;
1492
+ patch<T extends Record<string, unknown>>(
1493
+ key: string,
1494
+ partial: Partial<T>,
1495
+ options?: StateWriteOptions,
1496
+ ): Promise<StateValue<T>>;
1497
+ compareAndSet<T = unknown>(
1498
+ key: string,
1499
+ expectedVersion: number,
1500
+ value: T,
1501
+ options?: StateWriteOptions,
1502
+ ): Promise<StateCasResult<T>>;
1503
+ delete(key: string): Promise<void>;
1504
+ increment(
1505
+ key: string,
1506
+ field: string,
1507
+ delta?: number,
1508
+ options?: StateWriteOptions,
1509
+ ): Promise<StateValue<Record<string, unknown>>>;
1510
+ }
1511
+
1512
+ export interface ProviderRuntimeState {
1513
+ namespace(
1514
+ name: string,
1515
+ options: StateNamespaceOptions,
1516
+ ): ProviderStateNamespace;
480
1517
  }
481
1518
 
482
1519
  export interface ProviderContext {
@@ -484,10 +1521,14 @@ export interface ProviderContext {
484
1521
  credential: CredentialContext;
485
1522
  request?: ProviderRequestContext;
486
1523
  http: HttpClient;
487
- tls: TlsClient;
1524
+ cache: ProviderCache;
1525
+ state: ProviderRuntimeState;
1526
+ stealth: StealthClient;
488
1527
  browser: BrowserClient;
489
1528
  trace: TraceContext;
490
1529
  auth: AuthContext;
1530
+ stt: SttContext;
1531
+ choice: ProviderChoiceContext;
491
1532
  }
492
1533
 
493
1534
  export interface AuthConfig {
@@ -511,29 +1552,59 @@ export interface ContextDeclaration {
511
1552
  keys: string[];
512
1553
  }
513
1554
 
1555
+ export type OperationLifecycle = "stable" | "beta" | "deprecated" | "removed";
1556
+
1557
+ export interface OperationDeprecationMetadata {
1558
+ announcedAt: string;
1559
+ removalAfter: string;
1560
+ replacement?: string;
1561
+ migrationGuide: string;
1562
+ }
1563
+
1564
+ export interface OperationContractMetadata {
1565
+ /**
1566
+ * Callable operation contract version. Defaults to 1.0.0 for the clean
1567
+ * pre-GA baseline; it intentionally does not fall back to provider.version.
1568
+ */
1569
+ version?: string;
1570
+ lifecycle?: OperationLifecycle;
1571
+ deprecation?: OperationDeprecationMetadata;
1572
+ }
1573
+
514
1574
  export interface OperationDefinition<
515
1575
  TInput extends SchemaLike = SchemaLike,
516
1576
  TOutput extends SchemaLike = SchemaLike,
517
1577
  > {
518
- description?: string;
1578
+ descriptionKey?: ProviderLocaleKeyInput;
519
1579
  docs?: OperationDocMeta;
520
- whenToUse?: string[];
521
- whenNotToUse?: string[];
1580
+ whenToUseKeys?: readonly ProviderLocaleKeyInput[];
1581
+ whenNotToUseKeys?: readonly ProviderLocaleKeyInput[];
522
1582
  derivations?: Record<string, string>;
523
- inputExamples?: OperationInputExample[];
1583
+ inputExamples?: readonly OperationInputExample[];
524
1584
  annotations?: OperationAnnotations;
525
- tags?: string[];
1585
+ contract?: OperationContractMetadata;
1586
+ tags?: readonly string[];
526
1587
  relatedOperations?: OperationRelationships;
1588
+ toolRouter?: OperationToolRouterMetadata;
1589
+ observability?: OperationObservabilityConfig;
1590
+ transport?: OperationTransport;
1591
+ retryOnAuthRefresh?: boolean;
527
1592
  input: TInput;
528
1593
  output: TOutput;
529
1594
  handler(
530
1595
  ctx: ProviderContext,
531
1596
  input: InferSchemaOutput<TInput>,
532
- ): Promise<InferSchemaOutput<TOutput>>;
1597
+ ):
1598
+ | OperationHandlerResult<InferSchemaOutput<TOutput>>
1599
+ | Promise<OperationHandlerResult<InferSchemaOutput<TOutput>>>;
533
1600
  fixtures?: {
534
1601
  request: InferSchemaOutput<TInput>;
535
1602
  response: InferSchemaOutput<TOutput>;
536
1603
  };
1604
+ upstream?: {
1605
+ baseUrl?: string;
1606
+ proxy?: boolean | ProviderProxyPolicy;
1607
+ };
537
1608
  hints?: Record<string, string>;
538
1609
  healthCheck?: HealthCheckSuite<
539
1610
  InferSchemaOutput<TInput>,
@@ -551,16 +1622,19 @@ export interface ProviderDefinition {
551
1622
  profile: string;
552
1623
  platform: StealthPlatform;
553
1624
  };
554
- proxy?: boolean;
1625
+ proxy?: ProviderProxyConfig;
1626
+ stt?: ProviderSttConfig;
555
1627
  browser?: {
556
1628
  engine: BrowserEngine;
557
1629
  };
558
1630
  auth?: AuthConfig;
559
1631
  reviewed?: ProviderReviewed;
1632
+ access?: ProviderAccessConfig;
560
1633
  secrets?: ProviderSecretDeclaration[];
561
1634
  credential?: CredentialDeclaration;
562
1635
  context?: ContextDeclaration;
563
1636
  meta: ProviderMeta;
564
1637
  operations: Record<string, OperationDefinition<SchemaLike, SchemaLike>>;
565
1638
  healthMonitor?: ProviderHealthMonitorConfig;
1639
+ healthJourneys?: readonly HealthJourneyDefinition[];
566
1640
  }