@apifuse/provider-sdk 2.1.0-beta.2 → 2.1.0-beta.21

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 (231) hide show
  1. package/AUTHORING.md +330 -8
  2. package/CHANGELOG.md +89 -1
  3. package/README.md +64 -17
  4. package/SUBMISSION.md +86 -0
  5. package/bin/apifuse-check.ts +60 -6
  6. package/bin/apifuse-dev.ts +58 -8
  7. package/bin/apifuse-pack-check.ts +32 -2
  8. package/bin/apifuse-pack-smoke.ts +133 -6
  9. package/bin/apifuse-perf.ts +142 -49
  10. package/bin/apifuse-record.ts +182 -104
  11. package/bin/apifuse-submit-check.ts +3243 -0
  12. package/bin/apifuse.ts +1 -1
  13. package/dist/auth.d.ts +76 -0
  14. package/dist/auth.js +436 -0
  15. package/dist/ceremonies/index.d.ts +41 -0
  16. package/dist/ceremonies/index.js +490 -0
  17. package/dist/choice-token.d.ts +24 -0
  18. package/dist/choice-token.js +74 -0
  19. package/dist/cli/commands.d.ts +10 -0
  20. package/dist/cli/commands.js +80 -0
  21. package/dist/cli/create.d.ts +47 -0
  22. package/dist/cli/create.js +777 -0
  23. package/dist/cli/templates/provider/.dockerignore.tpl +22 -0
  24. package/dist/cli/templates/provider/.gitignore.tpl +22 -0
  25. package/dist/cli/templates/provider/AGENTS.md.tpl +87 -0
  26. package/dist/cli/templates/provider/CLAUDE.md.tpl +1 -0
  27. package/dist/cli/templates/provider/Dockerfile.tpl +7 -0
  28. package/dist/cli/templates/provider/README.md.tpl +163 -0
  29. package/dist/cli/templates/provider/dev.ts.tpl +5 -0
  30. package/dist/cli/templates/provider/domain/README.md.tpl +3 -0
  31. package/dist/cli/templates/provider/index.test.ts.tpl +13 -0
  32. package/dist/cli/templates/provider/index.ts.tpl +15 -0
  33. package/dist/cli/templates/provider/mappers/README.md.tpl +3 -0
  34. package/dist/cli/templates/provider/meta.ts.tpl +7 -0
  35. package/dist/cli/templates/provider/operations/index.ts.tpl +5 -0
  36. package/dist/cli/templates/provider/operations/ping.ts.tpl +24 -0
  37. package/dist/cli/templates/provider/schemas/ping.ts.tpl +24 -0
  38. package/dist/cli/templates/provider/skills/fixtures-and-recording/SKILL.md.tpl +58 -0
  39. package/dist/cli/templates/provider/skills/health-checks-and-fail-closed/SKILL.md.tpl +65 -0
  40. package/dist/cli/templates/provider/skills/normalization-standards/SKILL.md.tpl +57 -0
  41. package/dist/cli/templates/provider/skills/pagination-and-counts/SKILL.md.tpl +52 -0
  42. package/dist/cli/templates/provider/skills/upstream-contract-verification/SKILL.md.tpl +45 -0
  43. package/dist/cli/templates/provider/skills/upstream-notes/README.md.tpl +13 -0
  44. package/dist/cli/templates/provider/start.ts.tpl +5 -0
  45. package/dist/cli/templates/provider/upstream/README.md.tpl +3 -0
  46. package/dist/config/loader.d.ts +107 -0
  47. package/dist/config/loader.js +935 -0
  48. package/dist/contract-json.d.ts +9 -0
  49. package/dist/contract-json.js +51 -0
  50. package/dist/contract-serialization.d.ts +4 -0
  51. package/dist/contract-serialization.js +78 -0
  52. package/dist/contract-types.d.ts +49 -0
  53. package/dist/contract-types.js +1 -0
  54. package/dist/contract.d.ts +6 -0
  55. package/dist/contract.js +156 -0
  56. package/dist/define.d.ts +100 -0
  57. package/dist/define.js +1383 -0
  58. package/dist/dev.d.ts +9 -0
  59. package/dist/dev.js +15 -0
  60. package/dist/errors.d.ts +59 -0
  61. package/dist/errors.js +97 -0
  62. package/dist/i18n/catalog.d.ts +29 -0
  63. package/dist/i18n/catalog.js +159 -0
  64. package/dist/i18n/index.d.ts +2 -0
  65. package/dist/i18n/index.js +2 -0
  66. package/dist/i18n/keys.d.ts +10 -0
  67. package/dist/i18n/keys.js +34 -0
  68. package/dist/index.d.ts +42 -0
  69. package/dist/index.js +38 -0
  70. package/dist/lint.d.ts +74 -0
  71. package/dist/lint.js +729 -0
  72. package/dist/observability.d.ts +5 -0
  73. package/dist/observability.js +39 -0
  74. package/dist/provider.d.ts +11 -0
  75. package/dist/provider.js +9 -0
  76. package/dist/public-schema-field-lint.d.ts +2 -0
  77. package/dist/public-schema-field-lint.js +158 -0
  78. package/dist/recipes/gov-api.d.ts +19 -0
  79. package/dist/recipes/gov-api.js +72 -0
  80. package/dist/recipes/rest-api.d.ts +21 -0
  81. package/dist/recipes/rest-api.js +115 -0
  82. package/dist/runtime/auth-flow.d.ts +14 -0
  83. package/dist/runtime/auth-flow.js +46 -0
  84. package/dist/runtime/browser.d.ts +25 -0
  85. package/dist/runtime/browser.js +1237 -0
  86. package/dist/runtime/cache.d.ts +10 -0
  87. package/dist/runtime/cache.js +372 -0
  88. package/dist/runtime/choice.d.ts +15 -0
  89. package/dist/runtime/choice.js +435 -0
  90. package/dist/runtime/credential.d.ts +8 -0
  91. package/dist/runtime/credential.js +61 -0
  92. package/dist/runtime/env.d.ts +2 -0
  93. package/dist/runtime/env.js +10 -0
  94. package/dist/runtime/executor.d.ts +16 -0
  95. package/dist/runtime/executor.js +51 -0
  96. package/dist/runtime/http.d.ts +8 -0
  97. package/dist/runtime/http.js +726 -0
  98. package/dist/runtime/insights.d.ts +9 -0
  99. package/dist/runtime/insights.js +324 -0
  100. package/dist/runtime/instrumentation.d.ts +8 -0
  101. package/dist/runtime/instrumentation.js +269 -0
  102. package/dist/runtime/key-derivation.d.ts +24 -0
  103. package/dist/runtime/key-derivation.js +73 -0
  104. package/dist/runtime/keyring.d.ts +25 -0
  105. package/dist/runtime/keyring.js +93 -0
  106. package/dist/runtime/namespace.d.ts +9 -0
  107. package/dist/runtime/namespace.js +19 -0
  108. package/dist/runtime/otlp.d.ts +39 -0
  109. package/dist/runtime/otlp.js +103 -0
  110. package/dist/runtime/perf.d.ts +12 -0
  111. package/dist/runtime/perf.js +52 -0
  112. package/dist/runtime/prevalidate.d.ts +12 -0
  113. package/dist/runtime/prevalidate.js +173 -0
  114. package/dist/runtime/provider.d.ts +2 -0
  115. package/dist/runtime/provider.js +11 -0
  116. package/dist/runtime/proxy-errors.d.ts +21 -0
  117. package/dist/runtime/proxy-errors.js +83 -0
  118. package/dist/runtime/proxy-telemetry.d.ts +8 -0
  119. package/dist/runtime/proxy-telemetry.js +174 -0
  120. package/dist/runtime/redis.d.ts +17 -0
  121. package/dist/runtime/redis.js +82 -0
  122. package/dist/runtime/request-options.d.ts +3 -0
  123. package/dist/runtime/request-options.js +42 -0
  124. package/dist/runtime/state.d.ts +17 -0
  125. package/dist/runtime/state.js +344 -0
  126. package/dist/runtime/stealth.d.ts +21 -0
  127. package/dist/runtime/stealth.js +980 -0
  128. package/dist/runtime/stt.d.ts +22 -0
  129. package/dist/runtime/stt.js +480 -0
  130. package/dist/runtime/trace.d.ts +26 -0
  131. package/dist/runtime/trace.js +142 -0
  132. package/dist/runtime/waterfall.d.ts +12 -0
  133. package/dist/runtime/waterfall.js +147 -0
  134. package/dist/schema.d.ts +74 -0
  135. package/dist/schema.js +243 -0
  136. package/dist/serve.d.ts +1 -0
  137. package/dist/serve.js +1 -0
  138. package/dist/server/index.d.ts +3 -0
  139. package/dist/server/index.js +2 -0
  140. package/dist/server/serve.d.ts +64 -0
  141. package/dist/server/serve.js +1118 -0
  142. package/dist/server/types.d.ts +136 -0
  143. package/dist/server/types.js +86 -0
  144. package/dist/stealth/profiles.d.ts +4 -0
  145. package/dist/stealth/profiles.js +259 -0
  146. package/dist/stream.d.ts +44 -0
  147. package/dist/stream.js +151 -0
  148. package/dist/testing/helpers.d.ts +23 -0
  149. package/dist/testing/helpers.js +95 -0
  150. package/dist/testing/index.d.ts +2 -0
  151. package/dist/testing/index.js +2 -0
  152. package/dist/testing/run.d.ts +34 -0
  153. package/dist/testing/run.js +307 -0
  154. package/dist/types.d.ts +1467 -0
  155. package/dist/types.js +61 -0
  156. package/dist/utils/date.d.ts +6 -0
  157. package/dist/utils/date.js +101 -0
  158. package/dist/utils/parse.d.ts +16 -0
  159. package/dist/utils/parse.js +51 -0
  160. package/dist/utils/text.d.ts +4 -0
  161. package/dist/utils/text.js +14 -0
  162. package/dist/utils/transform.d.ts +8 -0
  163. package/dist/utils/transform.js +48 -0
  164. package/package.json +57 -29
  165. package/src/auth.ts +786 -0
  166. package/src/ceremonies/index.ts +8 -2
  167. package/src/choice-token.ts +165 -0
  168. package/src/cli/commands.ts +34 -11
  169. package/src/cli/create.ts +254 -128
  170. package/src/cli/templates/provider/.dockerignore.tpl +22 -0
  171. package/src/cli/templates/provider/.gitignore.tpl +22 -0
  172. package/src/cli/templates/provider/AGENTS.md.tpl +87 -0
  173. package/src/cli/templates/provider/CLAUDE.md.tpl +1 -0
  174. package/src/cli/templates/provider/README.md.tpl +87 -7
  175. package/src/cli/templates/provider/dev.ts.tpl +1 -1
  176. package/src/cli/templates/provider/domain/README.md.tpl +3 -0
  177. package/src/cli/templates/provider/index.ts.tpl +5 -47
  178. package/src/cli/templates/provider/mappers/README.md.tpl +3 -0
  179. package/src/cli/templates/provider/meta.ts.tpl +7 -0
  180. package/src/cli/templates/provider/operations/index.ts.tpl +5 -0
  181. package/src/cli/templates/provider/operations/ping.ts.tpl +24 -0
  182. package/src/cli/templates/provider/schemas/ping.ts.tpl +24 -0
  183. package/src/cli/templates/provider/skills/fixtures-and-recording/SKILL.md.tpl +58 -0
  184. package/src/cli/templates/provider/skills/health-checks-and-fail-closed/SKILL.md.tpl +65 -0
  185. package/src/cli/templates/provider/skills/normalization-standards/SKILL.md.tpl +57 -0
  186. package/src/cli/templates/provider/skills/pagination-and-counts/SKILL.md.tpl +52 -0
  187. package/src/cli/templates/provider/skills/upstream-contract-verification/SKILL.md.tpl +45 -0
  188. package/src/cli/templates/provider/skills/upstream-notes/README.md.tpl +13 -0
  189. package/src/cli/templates/provider/start.ts.tpl +1 -1
  190. package/src/cli/templates/provider/upstream/README.md.tpl +3 -0
  191. package/src/config/loader.ts +1224 -9
  192. package/src/contract-json.ts +75 -0
  193. package/src/contract-serialization.ts +89 -0
  194. package/src/contract-types.ts +52 -0
  195. package/src/contract.ts +216 -0
  196. package/src/define.ts +1820 -70
  197. package/src/errors.ts +27 -0
  198. package/src/i18n/catalog.ts +277 -0
  199. package/src/i18n/index.ts +2 -0
  200. package/src/i18n/keys.ts +64 -0
  201. package/src/index.ts +189 -9
  202. package/src/lint.ts +580 -73
  203. package/src/observability.ts +41 -0
  204. package/src/provider.ts +131 -4
  205. package/src/public-schema-field-lint.ts +237 -0
  206. package/src/runtime/auth-flow.ts +9 -0
  207. package/src/runtime/browser.ts +1054 -51
  208. package/src/runtime/cache.ts +528 -0
  209. package/src/runtime/choice.ts +760 -0
  210. package/src/runtime/executor.ts +32 -3
  211. package/src/runtime/http.ts +980 -195
  212. package/src/runtime/insights.ts +11 -11
  213. package/src/runtime/instrumentation.ts +12 -4
  214. package/src/runtime/key-derivation.ts +1 -1
  215. package/src/runtime/keyring.ts +4 -3
  216. package/src/runtime/proxy-errors.ts +132 -0
  217. package/src/runtime/proxy-telemetry.ts +253 -0
  218. package/src/runtime/redis.ts +116 -0
  219. package/src/runtime/request-options.ts +66 -0
  220. package/src/runtime/state.ts +563 -0
  221. package/src/runtime/stealth.ts +1336 -0
  222. package/src/runtime/stt.ts +629 -0
  223. package/src/runtime/trace.ts +1 -1
  224. package/src/schema.ts +363 -1
  225. package/src/server/serve.ts +1192 -75
  226. package/src/server/types.ts +37 -0
  227. package/src/stream.ts +210 -0
  228. package/src/testing/run.ts +40 -6
  229. package/src/types.ts +1283 -59
  230. package/src/runtime/tls.ts +0 -434
  231. 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,10 +127,362 @@ 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
192
  }
86
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
+ randomize?: HealthScheduleRandomization;
335
+ jitter?: Iso8601Duration;
336
+ }
337
+
338
+ export type HealthScheduleRandomization =
339
+ | {
340
+ mode: "centered";
341
+ maxOffset: Iso8601Duration;
342
+ }
343
+ | {
344
+ mode: "delayed";
345
+ maxDelay: Iso8601Duration;
346
+ };
347
+
348
+ export interface HealthJourneyStep {
349
+ id: string;
350
+ description?: string;
351
+ operationId?: string;
352
+ usesSmsMatcher?: string;
353
+ coversOperations?: readonly string[];
354
+ safeBoundary?: "paymentWebviewUrl" | "paymentUrl" | "none";
355
+ kind?: "operation" | "smsOtp" | "assertion" | "journal";
356
+ }
357
+
358
+ export interface HealthJourneyGatewayContext {
359
+ connect?(options?: {
360
+ providerId?: string;
361
+ externalRef?: string;
362
+ authMode?: "credentials" | "oauth2";
363
+ input?: Record<string, unknown>;
364
+ metadata?: Record<string, unknown>;
365
+ }): Promise<{ connectionId: string; rowVersion: number }>;
366
+ disconnect?(connection: {
367
+ connectionId: string;
368
+ rowVersion: number;
369
+ }): Promise<void>;
370
+ execute(
371
+ providerId: string,
372
+ operationId: string,
373
+ input: unknown,
374
+ options?: {
375
+ connectionId?: string;
376
+ requestId?: string;
377
+ /**
378
+ * Set false when the journey will record the semantic operation
379
+ * outcome itself through `ctx.event.operation()`. Transport success
380
+ * must not become a competing public health sample in that case.
381
+ */
382
+ recordOperationEvent?: boolean;
383
+ },
384
+ ): Promise<{
385
+ data: unknown;
386
+ status: number;
387
+ duration: number;
388
+ meta?: Record<string, unknown>;
389
+ }>;
390
+ }
391
+
392
+ export interface SmsPhoneIdentity {
393
+ id: string;
394
+ country: Iso3166Alpha2CountryCode | string;
395
+ e164: E164PhoneNumber | string;
396
+ nationalNumber: string;
397
+ displayName?: string;
398
+ }
399
+
400
+ export interface HealthJourneySmsContext {
401
+ resolvePhone(params?: { matcherId?: string }): Promise<SmsPhoneIdentity>;
402
+ waitForOtp(params: {
403
+ matcherId: string;
404
+ attemptId: string;
405
+ phoneId?: string;
406
+ phoneNumber?: string;
407
+ signal?: AbortSignal;
408
+ }): Promise<{ code: string; messageId: string; receivedAt: string }>;
409
+ }
410
+
411
+ export interface HealthJourneyJournalContext {
412
+ sideEffect<T>(params: {
413
+ stepId: string;
414
+ kind: string;
415
+ idempotencyKey: string;
416
+ run: () => Promise<T>;
417
+ }): Promise<T>;
418
+ }
419
+
420
+ export interface HealthJourneyEventContext {
421
+ /**
422
+ * Record an operation-level health outcome that was proven by the journey but
423
+ * not emitted by a direct `ctx.gateway.execute()` call, such as a recovery or
424
+ * manual-review assertion. This is intentionally narrow; it is not a generic
425
+ * event bus.
426
+ */
427
+ operation(params: {
428
+ operationId: string;
429
+ status: "ok" | "degraded" | "down" | "unknown" | "not_reached";
430
+ stepId?: string;
431
+ label?: string;
432
+ error?: string;
433
+ latencyMs?: number;
434
+ statusCode?: number;
435
+ metadata?: Record<string, unknown>;
436
+ }): Promise<void>;
437
+ }
438
+
439
+ export interface HealthJourneyRunContext {
440
+ attemptId: string;
441
+ providerId: string;
442
+ journeyId: string;
443
+ gateway: HealthJourneyGatewayContext;
444
+ sms: HealthJourneySmsContext;
445
+ journal: HealthJourneyJournalContext;
446
+ state: ProviderRuntimeState;
447
+ event: HealthJourneyEventContext;
448
+ signal: AbortSignal;
449
+ secrets: Record<string, string | undefined>;
450
+ }
451
+
452
+ export type HealthJourneyManualTriggerPolicy =
453
+ | { enabled: false; reason?: string }
454
+ | {
455
+ enabled: true;
456
+ requiresAcknowledgement: boolean;
457
+ risk: "read_only" | "writes_external_state" | "sms_or_payment";
458
+ /** ISO 8601 duration. Minimum time between manual executions. */
459
+ minManualInterval: Iso8601Duration;
460
+ publicRationale: string;
461
+ };
462
+
463
+ export interface HealthJourneyRunResult {
464
+ status?: "ok" | "degraded" | "down" | "unknown";
465
+ label?: string;
466
+ metadata?: Record<string, unknown>;
467
+ }
468
+
469
+ export interface HealthJourneyDefinition {
470
+ id: string;
471
+ title?: string;
472
+ description?: string;
473
+ schedule: HealthJourneySchedule;
474
+ coversOperations: readonly [string, ...string[]];
475
+ timeout?: Iso8601Duration;
476
+ cooldown?: Iso8601Duration;
477
+ smsMatchers?: readonly SmsOtpMatcherDefinition[];
478
+ requiredSecrets?: readonly string[];
479
+ manualTrigger?: HealthJourneyManualTriggerPolicy;
480
+ steps: readonly [HealthJourneyStep, ...HealthJourneyStep[]];
481
+ run?: (
482
+ ctx: HealthJourneyRunContext,
483
+ ) => Promise<HealthJourneyRunResult | undefined>;
484
+ }
485
+
87
486
  /**
88
487
  * Health-check authoring surface owned by `@apifuse/provider-sdk`.
89
488
  *
@@ -95,17 +494,14 @@ export interface OperationRelationships {
95
494
  * See `openspec/changes/enforce-sdk-operation-health-suite/design.md` §D1.
96
495
  */
97
496
 
98
- /** Polling intervals supported by the health-monitor runtime. */
99
- export type ProbeInterval =
100
- | "30s"
101
- | "1m"
102
- | "3m"
103
- | "5m"
104
- | "15m"
105
- | "30m"
106
- | "1h"
107
- | "24h";
497
+ /** Polling interval duration accepted by the health-monitor runtime. */
498
+ export type ProbeInterval = ms.StringValue;
108
499
 
500
+ /**
501
+ * Common probe interval examples retained for discoverability/backwards
502
+ * compatibility. This list is not exhaustive; any positive `ms`-style duration
503
+ * string accepted by `@types/ms` (for example `2m`, `8h`, or `1 day`) is valid.
504
+ */
109
505
  export const PROBE_INTERVALS: readonly ProbeInterval[] = [
110
506
  "30s",
111
507
  "1m",
@@ -114,9 +510,16 @@ export const PROBE_INTERVALS: readonly ProbeInterval[] = [
114
510
  "15m",
115
511
  "30m",
116
512
  "1h",
513
+ "2h",
514
+ "8h",
117
515
  "24h",
118
516
  ] as const;
119
517
 
518
+ export const HEALTH_CHECK_TIMEOUT_MS_MIN = 1;
519
+ export const HEALTH_CHECK_TIMEOUT_MS_MAX = 60_000;
520
+ export const HEALTH_CHECK_DEGRADED_THRESHOLD_MS_MIN = 1;
521
+ export const HEALTH_CHECK_DEGRADED_THRESHOLD_MS_MAX = 60_000;
522
+
120
523
  /**
121
524
  * Context passed to a `HealthCheckCase.assertions` lambda.
122
525
  * `data` is typed against the operation's declared output schema (TOutput).
@@ -128,6 +531,28 @@ export interface HealthCheckAssertionContext<TOutput = unknown> {
128
531
  readonly status: number;
129
532
  /** Wall-clock duration of the operation invocation, in milliseconds. */
130
533
  readonly durationMs: number;
534
+ /** Optional provider response metadata such as cache hit/stale flags. */
535
+ readonly meta?: Record<string, unknown>;
536
+ }
537
+
538
+ export interface HealthCheckInputPreparationContext<TInput = unknown> {
539
+ readonly providerId: string;
540
+ readonly operationId: string;
541
+ readonly input: TInput;
542
+ readonly connectionId?: string;
543
+ readonly gateway: {
544
+ execute: (
545
+ providerId: string,
546
+ operationId: string,
547
+ input: unknown,
548
+ options?: { connectionId?: string },
549
+ ) => Promise<{
550
+ status: number;
551
+ duration: number;
552
+ data: unknown;
553
+ meta?: Record<string, unknown>;
554
+ }>;
555
+ };
131
556
  }
132
557
 
133
558
  /**
@@ -156,6 +581,14 @@ export interface HealthCheckCase<TInput = unknown, TOutput = unknown> {
156
581
  description?: string;
157
582
  /** Input passed to the operation handler for this case. */
158
583
  input: TInput;
584
+ /**
585
+ * Optional runtime input preparation hook for volatile probes. Use this when
586
+ * the durable probe input must be derived from a live read-only operation
587
+ * immediately before the checked operation executes.
588
+ */
589
+ prepareInput?: (
590
+ ctx: HealthCheckInputPreparationContext<TInput>,
591
+ ) => TInput | Promise<TInput>;
159
592
  /**
160
593
  * Assertion executed against the operation's response and timing.
161
594
  *
@@ -175,6 +608,8 @@ export interface HealthCheckCase<TInput = unknown, TOutput = unknown> {
175
608
  | Promise<HealthCheckCaseResult>;
176
609
  /** Override per-case degradation threshold (ms); falls back to the suite default. */
177
610
  degradedThresholdMs?: number;
611
+ /** Override per-case timeout in milliseconds; falls back to the suite/provider/runtime default. */
612
+ timeoutMs?: number;
178
613
  /** Expected outcome for "negative" cases (e.g., expecting a degraded baseline). Default: `"ok"`. */
179
614
  expectedStatus?: "ok" | "degraded";
180
615
  /** Runtime gate (env-driven); if returns false the case is skipped & logged. */
@@ -188,8 +623,13 @@ export interface HealthCheckCase<TInput = unknown, TOutput = unknown> {
188
623
  export interface HealthCheckSuite<TInput = unknown, TOutput = unknown> {
189
624
  /** Polling interval for the suite. All cases share this cadence. */
190
625
  interval: ProbeInterval;
626
+ schedule?: {
627
+ randomize?: HealthScheduleRandomization;
628
+ };
191
629
  /** Per-case timeout in milliseconds. Default: 30000. */
192
630
  timeoutMs?: number;
631
+ /** Default degradation threshold for cases in this suite. Default: runtime threshold. */
632
+ degradedThresholdMs?: number;
193
633
  /** Non-empty list of cases. Empty arrays are rejected at definition time. */
194
634
  cases: [
195
635
  HealthCheckCase<TInput, TOutput>,
@@ -225,28 +665,49 @@ export interface HealthCheckUnsupported {
225
665
  */
226
666
  export interface ProviderHealthMonitorConfig {
227
667
  /**
228
- * Env-secret key names (e.g., "HEALTH_MONITOR_CATCHTABLE_PHONE") the
668
+ * Provider-wide default probe timeout in milliseconds. Individual
669
+ * `healthCheck.timeoutMs` and `healthCheck.cases[].timeoutMs` values take
670
+ * precedence. Defaults to the monitor runtime default.
671
+ */
672
+ defaultProbeTimeoutMs?: number;
673
+ /**
674
+ * Provider-wide default latency threshold in milliseconds before an
675
+ * otherwise successful probe is marked degraded. Suite/case thresholds take
676
+ * precedence. Defaults to the monitor runtime default.
677
+ */
678
+ defaultDegradedThresholdMs?: number;
679
+ /**
680
+ * Env-secret key names (e.g., "APIFUSE__HEALTH_MONITOR__CATCHTABLE_PHONE") the
229
681
  * synthetic-monitor runtime needs to execute probes that declare
230
682
  * `requiresConnection: true`.
231
683
  */
232
684
  requiredSecrets?: string[];
233
685
  /**
234
- * Runtime probe overrides keyed by probe id (for example
235
- * "catchtable/auth-flow" or "catchtable/waiting-lifecycle"). Use this for
236
- * health-monitor probes that are provider-scoped or cross-operation and
237
- * therefore cannot declare an `OperationDefinition.healthCheck.interval`.
686
+ * Mapping from provider auth ceremony input fields to runtime env-secret
687
+ * names. The health-monitor uses this to create a fresh connection for
688
+ * `requiresConnection: true` probes, then disconnects after execution.
689
+ */
690
+ credentialInputs?: Record<string, string>;
691
+ /**
692
+ * Runtime probe overrides keyed by generated registry probe id. Use this for
693
+ * operation health checks that need a runtime-specific interval or threshold
694
+ * without changing the provider-authored default suite.
238
695
  */
239
696
  probeOverrides?: Record<string, HealthMonitorProbeOverride>;
240
697
  /**
241
698
  * Override the default service account ID for this provider's probes.
242
- * Defaults to the runtime's `APIFUSE_SERVICE_ACCOUNT_ID` env var.
699
+ * Defaults to the runtime's `APIFUSE__HEALTH_MONITOR__SERVICE_ACCOUNT_ID` env var.
243
700
  */
244
701
  serviceAccount?: string;
245
702
  }
246
703
 
247
704
  export interface HealthMonitorProbeOverride {
248
- /** Optional runtime interval override. Must be one of PROBE_INTERVALS. */
705
+ /** Optional runtime interval override as a positive `ms`-style duration string. */
249
706
  interval?: ProbeInterval;
707
+ /** Optional timeout override for generated registry probes. */
708
+ timeoutMs?: number;
709
+ /** Optional degraded threshold override for generated registry probes. */
710
+ degradedThresholdMs?: number;
250
711
  }
251
712
 
252
713
  export interface OperationErrorCode {
@@ -257,10 +718,11 @@ export interface OperationErrorCode {
257
718
  }
258
719
 
259
720
  export interface OperationDocMeta {
260
- title?: string;
261
- description?: string;
262
- summary?: string;
263
- normalizationNotes?: string[];
721
+ titleKey?: ProviderLocaleKeyInput;
722
+ descriptionKey?: ProviderLocaleKeyInput;
723
+ summaryKey?: ProviderLocaleKeyInput;
724
+ markdownKey?: ProviderLocaleKeyInput;
725
+ normalizationNotesKeys?: ProviderLocaleKeyInput[];
264
726
  requestExample?: Record<string, unknown>;
265
727
  responseExample?: unknown;
266
728
  errorCodes?: OperationErrorCode[];
@@ -269,12 +731,12 @@ export interface OperationDocMeta {
269
731
  export type StealthPlatform = "macos" | "windows" | "linux" | "android" | "ios";
270
732
 
271
733
  export type BrowserEngine = "playwright-stealth" | "nodriver" | "selenium-uc";
272
-
273
734
  export interface BrowserOptions {
274
735
  headless?: boolean;
275
736
  stealth?: boolean;
276
737
  proxy?: string;
277
738
  engine?: BrowserEngine;
739
+ requireCdpPool?: boolean;
278
740
  }
279
741
 
280
742
  export interface StealthProfile {
@@ -295,42 +757,260 @@ export type ConnectionMode = AuthMode;
295
757
 
296
758
  export type ProviderReviewed = "first-party" | "community" | "staging";
297
759
 
760
+ export type ProviderAccessVisibility = "public" | "early_access";
761
+
762
+ export type ProviderProxyMode = "disabled" | "optional" | "required";
763
+
764
+ export type ProviderProxyProvider = "smartproxy" | "decodo" | "custom";
765
+
766
+ export type ProviderProxySessionAffinity =
767
+ | "request"
768
+ | "operation"
769
+ | "auth-flow"
770
+ | "connection";
771
+
772
+ export interface ProviderProxyPolicy {
773
+ /**
774
+ * Provider intent only. Transport details such as raw CONNECT, origin
775
+ * certificate verification, and vendor allocator endpoints are SDK-owned.
776
+ */
777
+ mode: ProviderProxyMode;
778
+ provider?: ProviderProxyProvider;
779
+ geo?: {
780
+ /** ISO 3166-1 alpha-2 country code, for example KR or US. */
781
+ country?: Iso3166Alpha2CountryCode;
782
+ subdivision?: string;
783
+ city?: string;
784
+ };
785
+ session?: {
786
+ affinity?: ProviderProxySessionAffinity;
787
+ lifetimeMinutes?: number;
788
+ poolSize?: number;
789
+ };
790
+ }
791
+
792
+ export type ProviderProxyConfig = boolean | ProviderProxyPolicy;
793
+
794
+ export interface ProviderAccessConfig {
795
+ /**
796
+ * Provider-level rollout visibility.
797
+ *
798
+ * - `public`: visible in public docs/catalog/OpenAPI and callable through
799
+ * the existing provider policy stack.
800
+ * - `early_access`: hidden from public discovery and callable only when the
801
+ * active customer organization has a provider-level access grant.
802
+ *
803
+ * This is intentionally provider-level only. It does not alter auth mode,
804
+ * operation schemas, health-check authoring, `openWorld`, or Connection
805
+ * requirements.
806
+ */
807
+ visibility?: ProviderAccessVisibility;
808
+ }
809
+
810
+ export type ProviderLogoSource = "asset" | "monogram" | "none";
811
+
812
+ export type ProviderLogoProfile =
813
+ | {
814
+ source: "asset";
815
+ path: string;
816
+ /**
817
+ * Absolute, customer-renderable URL emitted by discovery projections.
818
+ * Provider source definitions may omit this and let the registry projection
819
+ * derive it from the committed public asset path.
820
+ */
821
+ url?: string;
822
+ background?: string;
823
+ }
824
+ | {
825
+ source: "monogram" | "none";
826
+ background?: string;
827
+ fallbackReason: string;
828
+ };
829
+
830
+ export type ProviderPublicConnectionMode =
831
+ | "apifuse_managed"
832
+ | "workspace_enabled"
833
+ | "user_connected"
834
+ | "no_connection_required";
835
+
836
+ export type ProviderSupportLevel = "stable" | "beta" | "experimental";
837
+
838
+ export interface ProviderPublicProfile {
839
+ displayNameKey?: ProviderLocaleKeyInput;
840
+ shortDescriptionKey?: ProviderLocaleKeyInput;
841
+ longDescriptionKey?: ProviderLocaleKeyInput;
842
+ logo?: ProviderLogoProfile;
843
+ category?: string;
844
+ tags?: readonly string[];
845
+ capabilityKeys?: readonly ProviderLocaleKeyInput[];
846
+ examplePromptKeys?: readonly ProviderLocaleKeyInput[];
847
+ setupSummaryKey?: ProviderLocaleKeyInput;
848
+ connectionMode?: ProviderPublicConnectionMode;
849
+ requirementKeys?: readonly ProviderLocaleKeyInput[];
850
+ limitationKeys?: readonly ProviderLocaleKeyInput[];
851
+ availability?: {
852
+ regions?: readonly string[];
853
+ supportLevel?: ProviderSupportLevel;
854
+ };
855
+ /**
856
+ * Brand primary color as a 6-digit hex string (e.g. "#1a73e8").
857
+ * Single source of truth for all provider-specific color expressions
858
+ * (mood wash, monogram fallback, icon tint). The UI derives subtle washes
859
+ * via color-mix; provider definitions do not control mood percentages.
860
+ */
861
+ primaryColor?: string;
862
+ }
863
+
298
864
  export interface ProviderMeta {
299
865
  displayName: string;
300
- description?: string;
866
+ displayNameKey?: ProviderLocaleKeyInput;
867
+ descriptionKey: ProviderLocaleKeyInput;
301
868
  category: string;
302
- tags?: string[];
869
+ tags?: readonly string[];
303
870
  icon?: string;
304
- docTitle?: string;
305
- docDescription?: string;
306
- docSummary?: string;
307
- normalizationNotes?: string[];
871
+ docTitleKey?: ProviderLocaleKeyInput;
872
+ docDescriptionKey?: ProviderLocaleKeyInput;
873
+ docSummaryKey?: ProviderLocaleKeyInput;
874
+ docMarkdownKey?: ProviderLocaleKeyInput;
875
+ normalizationNotesKeys?: readonly ProviderLocaleKeyInput[];
308
876
  environment?: "staging";
309
877
  purpose?: string;
878
+ purposeKey?: ProviderLocaleKeyInput;
879
+ publicProfile?: ProviderPublicProfile;
880
+ contract?: {
881
+ publicSchemaFieldNames?: "normalized";
882
+ };
883
+ }
884
+
885
+ export type RequestParamPrimitive =
886
+ | string
887
+ | number
888
+ | boolean
889
+ | null
890
+ | undefined;
891
+ export type RequestParamValue =
892
+ | RequestParamPrimitive
893
+ | readonly RequestParamPrimitive[];
894
+ export type RequestParams = Record<string, RequestParamValue>;
895
+
896
+ export const HttpRetryPreset = {
897
+ Off: "off",
898
+ TransportTransient: "transport_transient",
899
+ SafeRead: "safe_read",
900
+ AggressiveRead: "aggressive_read",
901
+ RateLimitAware: "rate_limit_aware",
902
+ } as const;
903
+ export type HttpRetryPreset =
904
+ (typeof HttpRetryPreset)[keyof typeof HttpRetryPreset];
905
+
906
+ export const HttpRetryJitter = {
907
+ None: "none",
908
+ Full: "full",
909
+ Equal: "equal",
910
+ } as const;
911
+ export type HttpRetryJitter =
912
+ (typeof HttpRetryJitter)[keyof typeof HttpRetryJitter];
913
+
914
+ export const HttpRetryDelayStrategy = {
915
+ Fixed: "fixed",
916
+ Exponential: "exponential",
917
+ } as const;
918
+ export type HttpRetryDelayStrategy =
919
+ (typeof HttpRetryDelayStrategy)[keyof typeof HttpRetryDelayStrategy];
920
+
921
+ export const HttpRetryAfterPolicy = {
922
+ Ignore: "ignore",
923
+ /** Honor Retry-After up to maxDelayMs. */
924
+ Respect: "respect",
925
+ /** Honor Retry-After but also cap it to the SDK-computed backoff delay. */
926
+ Cap: "cap",
927
+ } as const;
928
+ export type HttpRetryAfterPolicy =
929
+ (typeof HttpRetryAfterPolicy)[keyof typeof HttpRetryAfterPolicy];
930
+
931
+ export const HttpRetryUnsafeMethodPolicy = {
932
+ Reject: "reject",
933
+ AllowExplicitUnsafe: "allow_explicit_unsafe",
934
+ } as const;
935
+ export type HttpRetryUnsafeMethodPolicy =
936
+ (typeof HttpRetryUnsafeMethodPolicy)[keyof typeof HttpRetryUnsafeMethodPolicy];
937
+
938
+ export interface HttpRetryOptions {
939
+ preset?: HttpRetryPreset;
940
+ /** Total logical ctx.http attempts, including the first attempt. */
941
+ attempts?: number;
942
+ methods?: readonly HttpMethod[];
943
+ statusCodes?: readonly number[];
944
+ errorCodes?: readonly string[];
945
+ delayStrategy?: HttpRetryDelayStrategy;
946
+ baseDelayMs?: number;
947
+ maxDelayMs?: number;
948
+ jitter?: HttpRetryJitter;
949
+ retryAfter?: HttpRetryAfterPolicy;
950
+ unsafeMethodPolicy?: HttpRetryUnsafeMethodPolicy;
951
+ }
952
+
953
+ export interface HttpRetrySummary {
954
+ attempts: number;
955
+ retries: number;
956
+ preset?: HttpRetryPreset;
957
+ transport: "native";
958
+ lastErrorCode?: string;
959
+ lastStatus?: number;
310
960
  }
311
961
 
312
962
  export interface RequestOptions {
313
963
  headers?: Record<string, string>;
314
- params?: Record<string, string>;
964
+ params?: RequestParams;
315
965
  proxy?: string;
316
966
  timeout?: number;
967
+ /**
968
+ * Defaults to true. Set to false when callers need to inspect upstream
969
+ * non-2xx bodies themselves instead of converting them to TransportError.
970
+ */
971
+ throwOnHttpError?: boolean;
972
+ retry?: boolean | HttpRetryPreset | HttpRetryOptions;
317
973
  }
318
974
 
319
- export interface TlsFetchOptions extends RequestOptions {
320
- method?: string;
975
+ export type HttpMethod =
976
+ | "HEAD"
977
+ | "head"
978
+ | "GET"
979
+ | "get"
980
+ | "POST"
981
+ | "post"
982
+ | "PUT"
983
+ | "put"
984
+ | "DELETE"
985
+ | "delete"
986
+ | "OPTIONS"
987
+ | "options"
988
+ | "TRACE"
989
+ | "trace"
990
+ | "PATCH"
991
+ | "patch";
992
+
993
+ export interface StealthFetchOptions extends RequestOptions {
994
+ method?: HttpMethod;
321
995
  body?: string | Buffer;
996
+ redirect?: "follow" | "manual" | "error";
997
+ /**
998
+ * Offsets policy-managed proxy pool selection for caller-managed retries.
999
+ * Use when a request receives an upstream challenge page rather than a
1000
+ * transport error, so the next logical retry does not restart at the same
1001
+ * operation-affinity proxy.
1002
+ */
1003
+ proxyAttemptOffset?: number;
1004
+ /** Override the configured browser-like stealth profile for this request. */
322
1005
  profile?: string;
323
1006
  /**
324
- * Defaults to true. Set to false when callers need to inspect upstream
325
- * non-2xx bodies themselves instead of converting them to TransportError.
1007
+ * Stealth transport certificate controls. Use only for proxy products that
1008
+ * terminate CONNECT with a private CA instead of tunneling the origin
1009
+ * certificate chain.
326
1010
  */
327
- throwOnHttpError?: boolean;
328
- tls?: {
329
- ja3?: string;
330
- h2?: Record<string, unknown>;
1011
+ stealth?: {
331
1012
  insecureSkipVerify?: boolean;
332
1013
  };
333
- headerOrder?: string[];
334
1014
  }
335
1015
 
336
1016
  export interface CookieJar {
@@ -340,9 +1020,20 @@ export interface CookieJar {
340
1020
  find?(predicate: (cookie: string) => boolean): string | undefined;
341
1021
  }
342
1022
 
343
- export interface DeclarativeTlsResponse {
1023
+ export interface StealthSessionCookies extends CookieJar {
1024
+ has(name: string): boolean;
1025
+ setFromCookieStrings(cookieStrings: readonly string[]): void;
1026
+ toHeader(): string;
1027
+ snapshot(): Record<string, string>;
1028
+ restore(cookies: Record<string, string>): void;
1029
+ clear(): void;
1030
+ }
1031
+
1032
+ export interface DeclarativeStealthResponse {
344
1033
  status: number;
345
1034
  ok: boolean;
1035
+ url?: string;
1036
+ redirected?: boolean;
346
1037
  headers: Record<string, string>;
347
1038
  rawHeaders: [string, string][];
348
1039
  body: string;
@@ -350,16 +1041,45 @@ export interface DeclarativeTlsResponse {
350
1041
  tlsInfo?: { protocol?: string; cipher?: string; [key: string]: unknown };
351
1042
  cookies: CookieJar;
352
1043
  json<T>(): Promise<T>;
1044
+ arrayBuffer(): Promise<ArrayBuffer>;
1045
+ bytes(): Promise<Uint8Array>;
353
1046
  }
354
1047
 
355
- export type TlsResponse = DeclarativeTlsResponse;
1048
+ export type StealthResponse = DeclarativeStealthResponse;
356
1049
 
357
1050
  export type RequestWithMethodOptions = RequestOptions & {
358
1051
  method?: string;
1052
+ body?: unknown;
359
1053
  };
360
1054
 
361
- export interface TlsSession {
362
- fetch(url: string, options?: TlsFetchOptions): Promise<TlsResponse>;
1055
+ export interface StealthRedirectHop {
1056
+ url: string;
1057
+ status: number;
1058
+ method: string;
1059
+ location?: string;
1060
+ nextUrl?: string;
1061
+ }
1062
+
1063
+ export interface StealthRedirectRunOptions
1064
+ extends Omit<StealthFetchOptions, "redirect"> {
1065
+ url: string;
1066
+ maxHops?: number;
1067
+ stopWhen?: (hop: StealthRedirectHop) => boolean | Promise<boolean>;
1068
+ }
1069
+
1070
+ export interface StealthRedirectRunResult {
1071
+ final: StealthResponse;
1072
+ hops: StealthRedirectHop[];
1073
+ reason: "completed" | "stopped" | "max_hops" | "missing_location" | "loop";
1074
+ cookies: Record<string, string>;
1075
+ }
1076
+
1077
+ export interface StealthSession {
1078
+ fetch(url: string, options?: StealthFetchOptions): Promise<StealthResponse>;
1079
+ cookies: StealthSessionCookies;
1080
+ redirects: {
1081
+ run(options: StealthRedirectRunOptions): Promise<StealthRedirectRunResult>;
1082
+ };
363
1083
  close(): void;
364
1084
  }
365
1085
 
@@ -369,6 +1089,9 @@ export interface ApiFuseResponse<T> {
369
1089
  requestId: string;
370
1090
  duration: number;
371
1091
  cached?: boolean;
1092
+ stale?: boolean;
1093
+ cache?: ProviderCacheResponseMeta;
1094
+ retry?: HttpRetrySummary;
372
1095
  };
373
1096
  }
374
1097
 
@@ -379,8 +1102,41 @@ export interface HttpResponse<T = unknown> {
379
1102
  data: T;
380
1103
  json<U = T>(): Promise<U>;
381
1104
  text(): Promise<string>;
1105
+ arrayBuffer(): Promise<ArrayBuffer>;
1106
+ bytes(): Promise<Uint8Array>;
382
1107
  }
383
1108
 
1109
+ export interface HttpStreamResponse {
1110
+ status: number;
1111
+ ok: boolean;
1112
+ headers: Record<string, string>;
1113
+ body: ReadableStream<Uint8Array>;
1114
+ bytes(): AsyncIterable<Uint8Array>;
1115
+ textChunks(): AsyncIterable<string>;
1116
+ lines(): AsyncIterable<string>;
1117
+ }
1118
+
1119
+ export interface SseMessage {
1120
+ event: string;
1121
+ data: string;
1122
+ id?: string;
1123
+ retry?: number;
1124
+ json<T = unknown>(): T;
1125
+ }
1126
+
1127
+ export interface ProviderStreamEvent<TData = unknown> {
1128
+ event: string;
1129
+ data: TData;
1130
+ id?: string;
1131
+ retry?: number;
1132
+ }
1133
+
1134
+ export type OperationHandlerResult<TOutput> =
1135
+ | TOutput
1136
+ | Response
1137
+ | ReadableStream<Uint8Array>
1138
+ | AsyncIterable<ProviderStreamEvent>;
1139
+
384
1140
  export interface HttpClient {
385
1141
  request(url: string, opts?: RequestWithMethodOptions): Promise<HttpResponse>;
386
1142
  get(url: string, options?: RequestOptions): Promise<HttpResponse>;
@@ -395,18 +1151,185 @@ export interface HttpClient {
395
1151
  options?: RequestOptions,
396
1152
  ): Promise<HttpResponse>;
397
1153
  delete(url: string, options?: RequestOptions): Promise<HttpResponse>;
1154
+ stream(
1155
+ url: string,
1156
+ options?: RequestWithMethodOptions,
1157
+ ): Promise<HttpStreamResponse>;
1158
+ sse(
1159
+ url: string,
1160
+ options?: RequestWithMethodOptions,
1161
+ ): Promise<AsyncIterable<SseMessage>>;
398
1162
  }
399
1163
 
400
- export interface TlsClient {
401
- fetch(url: string, options?: TlsFetchOptions): Promise<TlsResponse>;
402
- createSession(opts?: { profile?: string }): TlsSession;
1164
+ export interface ProviderCacheKeyOptions {
1165
+ /**
1166
+ * Additional field names to omit from stable key material. The SDK always
1167
+ * omits known secret-bearing names such as serviceKey, authorization,
1168
+ * cookie, token, password, and secret.
1169
+ */
1170
+ redactFields?: string[];
1171
+ }
1172
+
1173
+ export interface ProviderCacheGetOrSetOptions {
1174
+ /** Freshness TTL. A fresh hit returns without calling the loader. */
1175
+ ttlMs: number;
1176
+ /**
1177
+ * Optional stale window after ttlMs. If the loader fails while the entry is
1178
+ * still inside this window, stale data is returned and marked stale.
1179
+ */
1180
+ staleIfErrorMs?: number;
1181
+ /** Optional jitter applied to writes to avoid synchronized expiry. */
1182
+ jitterPct?: number;
1183
+ }
1184
+
1185
+ export interface ProviderCacheLookupMeta {
1186
+ key: string;
1187
+ hit: boolean;
1188
+ stale: boolean;
1189
+ ageMs?: number;
1190
+ source: "redis" | "memory" | "loader";
1191
+ }
1192
+
1193
+ export interface ProviderCacheResult<T> {
1194
+ value: T;
1195
+ meta: ProviderCacheLookupMeta;
1196
+ }
1197
+
1198
+ export interface ProviderCacheResponseMeta {
1199
+ hit: boolean;
1200
+ stale: boolean;
1201
+ keys: string[];
1202
+ source?: "redis" | "memory" | "loader" | "mixed";
1203
+ }
1204
+
1205
+ export interface ProviderCache {
1206
+ key(
1207
+ namespace: string,
1208
+ parts: unknown,
1209
+ options?: ProviderCacheKeyOptions,
1210
+ ): string;
1211
+ get<T = unknown>(key: string): Promise<ProviderCacheResult<T> | null>;
1212
+ set<T = unknown>(
1213
+ key: string,
1214
+ value: T,
1215
+ options: ProviderCacheGetOrSetOptions,
1216
+ ): Promise<void>;
1217
+ delete(key: string): Promise<void>;
1218
+ getOrSet<T = unknown>(
1219
+ key: string,
1220
+ loader: () => Promise<T>,
1221
+ options: ProviderCacheGetOrSetOptions,
1222
+ ): Promise<ProviderCacheResult<T>>;
1223
+ responseMeta(): ProviderCacheResponseMeta | undefined;
1224
+ }
1225
+
1226
+ export interface StealthClient {
1227
+ fetch(url: string, options?: StealthFetchOptions): Promise<StealthResponse>;
1228
+ createSession(opts?: { profile?: string }): StealthSession;
1229
+ close?(): void;
403
1230
  }
404
1231
 
405
1232
  export interface BrowserClient {
406
1233
  readonly engine: BrowserEngine;
407
- newPage(): Promise<unknown>;
1234
+ close?(): Promise<void>;
1235
+ newPage(): Promise<BrowserPage>;
1236
+ rawPage(): Promise<BrowserPage>;
1237
+ withIsolatedContext<T>(
1238
+ handler: (page: BrowserPage) => Promise<T>,
1239
+ ): Promise<T>;
1240
+ solveChallenge(
1241
+ request: BrowserChallengeRequest,
1242
+ ): Promise<BrowserChallengeResult>;
1243
+ }
1244
+
1245
+ export interface BrowserLocator {
1246
+ click(): Promise<void>;
1247
+ fill(text: string): Promise<void>;
1248
+ textContent(): Promise<string | null>;
1249
+ waitFor(options?: { timeout?: number }): Promise<void>;
1250
+ }
1251
+
1252
+ export interface BrowserFrame {
1253
+ id: string;
1254
+ name?: string;
1255
+ parentId?: string;
1256
+ url(): Promise<string>;
1257
+ title(): Promise<string>;
1258
+ content(): Promise<string>;
1259
+ evaluate<T>(fn: string | (() => T)): Promise<T>;
1260
+ locator(selector: string): BrowserLocator;
408
1261
  }
409
1262
 
1263
+ export type BrowserResourceMethod = "GET" | "HEAD";
1264
+
1265
+ export type BrowserResourceRequest = {
1266
+ readonly url: string;
1267
+ readonly method: BrowserResourceMethod;
1268
+ readonly resourceType?: string;
1269
+ readonly headers: Readonly<Record<string, string>>;
1270
+ };
1271
+
1272
+ export type BrowserResourceBody = Buffer | Uint8Array | ArrayBuffer | string;
1273
+
1274
+ export type BrowserResourceDecision =
1275
+ | {
1276
+ readonly action: "fulfill";
1277
+ readonly status?: number;
1278
+ readonly headers?: Readonly<Record<string, string>>;
1279
+ readonly body?: BrowserResourceBody;
1280
+ }
1281
+ | {
1282
+ readonly action: "block";
1283
+ readonly reason?: string;
1284
+ };
1285
+
1286
+ export type BrowserResourceRoute = {
1287
+ readonly match:
1288
+ | string
1289
+ | RegExp
1290
+ | ((request: BrowserResourceRequest) => boolean);
1291
+ readonly handle: (
1292
+ request: BrowserResourceRequest,
1293
+ ) => Promise<BrowserResourceDecision> | BrowserResourceDecision;
1294
+ };
1295
+
1296
+ export type BrowserResourcePolicy = {
1297
+ readonly defaultAction?: "block";
1298
+ readonly allowedMethods?: readonly BrowserResourceMethod[];
1299
+ readonly routes: readonly BrowserResourceRoute[];
1300
+ };
1301
+
1302
+ export interface BrowserPage extends BrowserFrame {
1303
+ close(): Promise<void>;
1304
+ fill(selector: string, text: string): Promise<void>;
1305
+ goto(url: string): Promise<void>;
1306
+ pageId?: string;
1307
+ screenshot(options?: { fullPage?: boolean }): Promise<Buffer>;
1308
+ click(selector: string): Promise<void>;
1309
+ type(selector: string, text: string): Promise<void>;
1310
+ waitForSelector(
1311
+ selector: string,
1312
+ options?: { timeout?: number },
1313
+ ): Promise<void>;
1314
+ frames(): Promise<BrowserFrame[]>;
1315
+ withResourcePolicy<T>(
1316
+ policy: BrowserResourcePolicy,
1317
+ run: () => Promise<T>,
1318
+ ): Promise<T>;
1319
+ }
1320
+
1321
+ export type BrowserChallengeRequest = {
1322
+ type: "recaptcha";
1323
+ siteKey?: string;
1324
+ timeout?: number;
1325
+ };
1326
+
1327
+ export type BrowserChallengeResult = {
1328
+ type: BrowserChallengeRequest["type"];
1329
+ solved: boolean;
1330
+ frameUrl?: string;
1331
+ };
1332
+
410
1333
  export type TraceAttributeValue = string | number | boolean;
411
1334
 
412
1335
  export interface TraceSpan {
@@ -462,6 +1385,107 @@ export interface ProviderRequestContext {
462
1385
  headers: Record<string, string>;
463
1386
  }
464
1387
 
1388
+ export interface ProviderChoiceBindingOptions {
1389
+ connection?: boolean;
1390
+ credentialKeys?: readonly string[];
1391
+ }
1392
+
1393
+ export type ProviderChoiceStorageOptions =
1394
+ | {
1395
+ readonly mode: "inline";
1396
+ }
1397
+ | {
1398
+ readonly mode: "server";
1399
+ readonly namespace: string;
1400
+ readonly state?: ProviderRuntimeState;
1401
+ readonly ttl?: ProviderStateDurationString;
1402
+ readonly maxEntries: number;
1403
+ readonly maxValueBytes: number;
1404
+ readonly unavailable?: "reject";
1405
+ }
1406
+ | {
1407
+ readonly mode: "auto";
1408
+ readonly namespace: string;
1409
+ readonly state?: ProviderRuntimeState;
1410
+ readonly ttl?: ProviderStateDurationString;
1411
+ readonly maxInlineBytes: number;
1412
+ readonly maxEntries: number;
1413
+ readonly maxValueBytes: number;
1414
+ readonly unavailable?: "reject";
1415
+ };
1416
+
1417
+ export interface ProviderChoiceIssueOptions<
1418
+ TPayload extends Record<string, unknown>,
1419
+ > {
1420
+ prefix: string;
1421
+ purpose: string;
1422
+ payload: TPayload;
1423
+ ttlMs: number;
1424
+ nowMs?: number;
1425
+ bind?: ProviderChoiceBindingOptions;
1426
+ storage?: ProviderChoiceStorageOptions;
1427
+ }
1428
+
1429
+ export interface ProviderChoiceParseOptions {
1430
+ token: string;
1431
+ prefix: string;
1432
+ purpose: string;
1433
+ ttlMs?: number;
1434
+ nowMs?: number;
1435
+ futureToleranceMs?: number;
1436
+ bind?: ProviderChoiceBindingOptions;
1437
+ storage?: ProviderChoiceStorageOptions;
1438
+ }
1439
+
1440
+ export interface ProviderChoiceContext {
1441
+ issue<TPayload extends Record<string, unknown>>(
1442
+ options: ProviderChoiceIssueOptions<TPayload> & {
1443
+ readonly storage?: { readonly mode: "inline" };
1444
+ },
1445
+ ): string;
1446
+ issue<TPayload extends Record<string, unknown>>(
1447
+ options: ProviderChoiceIssueOptions<TPayload> & {
1448
+ readonly storage: Extract<
1449
+ ProviderChoiceStorageOptions,
1450
+ { readonly mode: "server" }
1451
+ >;
1452
+ },
1453
+ ): Promise<string>;
1454
+ issue<TPayload extends Record<string, unknown>>(
1455
+ options: ProviderChoiceIssueOptions<TPayload> & {
1456
+ readonly storage: Extract<
1457
+ ProviderChoiceStorageOptions,
1458
+ { readonly mode: "auto" }
1459
+ >;
1460
+ },
1461
+ ): string | Promise<string>;
1462
+ issue<TPayload extends Record<string, unknown>>(
1463
+ options: ProviderChoiceIssueOptions<TPayload>,
1464
+ ): string | Promise<string>;
1465
+ parse(
1466
+ options: ProviderChoiceParseOptions & {
1467
+ readonly storage?: { readonly mode: "inline" };
1468
+ },
1469
+ ): Record<string, unknown>;
1470
+ parse(
1471
+ options: ProviderChoiceParseOptions & {
1472
+ readonly storage: Extract<
1473
+ ProviderChoiceStorageOptions,
1474
+ { readonly mode: "server" }
1475
+ >;
1476
+ },
1477
+ ): Promise<Record<string, unknown>>;
1478
+ parse(
1479
+ options: ProviderChoiceParseOptions & {
1480
+ readonly storage: Extract<
1481
+ ProviderChoiceStorageOptions,
1482
+ { readonly mode: "auto" }
1483
+ >;
1484
+ },
1485
+ ): Record<string, unknown> | Promise<Record<string, unknown>>;
1486
+ parse(options: ProviderChoiceParseOptions): Record<string, unknown>;
1487
+ }
1488
+
465
1489
  export interface ContextScratchpad {
466
1490
  get(key: string): unknown;
467
1491
  set(key: string, value: unknown): void;
@@ -470,14 +1494,96 @@ export interface ContextScratchpad {
470
1494
 
471
1495
  export type FlowContextStore = ContextScratchpad;
472
1496
 
1497
+ export type AuthSafeJson =
1498
+ | string
1499
+ | number
1500
+ | boolean
1501
+ | null
1502
+ | readonly AuthSafeJson[]
1503
+ | { readonly [key: string]: AuthSafeJson };
1504
+
1505
+ export type AuthSafeData = { readonly [key: string]: AuthSafeJson };
1506
+
1507
+ export type AuthAbortRetry = "never" | "retry" | "after_user_action";
1508
+
1509
+ export type AuthAbortData = Record<string, unknown> & {
1510
+ readonly code: string;
1511
+ readonly message?: string;
1512
+ readonly retry?: AuthAbortRetry;
1513
+ readonly actionHint?: AuthSafeJson;
1514
+ readonly fieldErrors?: { readonly [field: string]: string };
1515
+ readonly details?: AuthSafeData;
1516
+ };
1517
+
1518
+ export interface AuthFlowTerminalContext {
1519
+ readonly signal?: AbortSignal;
1520
+ readonly deadline?: string;
1521
+ complete<TCredential extends Record<string, string>>(options: {
1522
+ readonly credential: TCredential;
1523
+ readonly metadata?: AuthSafeData;
1524
+ readonly data?: AuthSafeData;
1525
+ readonly turnId?: string;
1526
+ readonly expiresAt?: string;
1527
+ }): AuthTurn;
1528
+ abort(options: {
1529
+ readonly code: string;
1530
+ readonly message?: string;
1531
+ readonly retry?: AuthAbortRetry;
1532
+ readonly actionHint?: AuthSafeJson;
1533
+ readonly fieldErrors?: { readonly [field: string]: string };
1534
+ readonly data?: AuthSafeData;
1535
+ readonly turnId?: string;
1536
+ readonly expiresAt?: string;
1537
+ }): AuthTurn;
1538
+ nextForm(
1539
+ options: {
1540
+ readonly hintKey?: ProviderLocaleKeyInput;
1541
+ readonly data?: AuthSafeData;
1542
+ readonly turnId?: string;
1543
+ readonly expiresAt?: string;
1544
+ readonly timing?: AuthTurn["timing"];
1545
+ } & (
1546
+ | {
1547
+ readonly fields: Record<
1548
+ string,
1549
+ {
1550
+ readonly type?: "string" | "email" | "password" | "otp";
1551
+ readonly labelKey?: ProviderLocaleKeyInput;
1552
+ readonly descriptionKey?: ProviderLocaleKeyInput;
1553
+ readonly placeholderKey?: ProviderLocaleKeyInput;
1554
+ readonly required?: boolean;
1555
+ readonly sensitive?: boolean;
1556
+ }
1557
+ >;
1558
+ readonly expectedInput?: never;
1559
+ }
1560
+ | {
1561
+ readonly expectedInput: Record<string, unknown>;
1562
+ readonly fields?: never;
1563
+ }
1564
+ ),
1565
+ ): AuthTurn;
1566
+ nextPoll(options?: {
1567
+ readonly hintKey?: ProviderLocaleKeyInput;
1568
+ readonly data?: AuthSafeData;
1569
+ readonly turnId?: string;
1570
+ readonly expiresAt?: string;
1571
+ readonly timing?: AuthTurn["timing"];
1572
+ }): AuthTurn;
1573
+ }
1574
+
473
1575
  export interface FlowContext {
474
1576
  connectionId?: string;
475
1577
  externalRef?: string;
476
1578
  tenantId: string;
477
1579
  providerId: string;
478
1580
  http: HttpClient;
1581
+ stealth: StealthClient;
479
1582
  env: EnvContext;
1583
+ credential?: CredentialContext;
480
1584
  context: ContextScratchpad;
1585
+ stt: SttContext;
1586
+ auth: AuthFlowTerminalContext;
481
1587
  }
482
1588
 
483
1589
  export interface AuthTurn {
@@ -486,23 +1592,104 @@ export interface AuthTurn {
486
1592
  expiresAt?: string;
487
1593
  data?: Record<string, unknown>;
488
1594
  expectedInput?: Record<string, unknown>;
1595
+ /**
1596
+ * @deprecated Compatibility-only materialized provider auth hint.
1597
+ * Provider source must emit hintKey; SDK/server boundaries may materialize
1598
+ * this field from provider locale catalogs for legacy clients.
1599
+ */
489
1600
  hint?: string;
1601
+ /** Provider locale catalog key for the auth turn hint. */
1602
+ hintKey?: ProviderLocaleKeyInput;
490
1603
  timing?: {
491
1604
  suggestedPollIntervalMs?: number;
492
1605
  maxWaitMs?: number;
493
1606
  };
494
1607
  }
495
1608
 
496
- export type AuthFlowHandler = (
1609
+ export type AuthFlowStartHandler = (ctx: FlowContext) => Promise<AuthTurn>;
1610
+
1611
+ export type AuthFlowInputHandler = (
497
1612
  ctx: FlowContext,
498
1613
  input?: Record<string, unknown>,
499
1614
  ) => Promise<AuthTurn>;
500
1615
 
501
1616
  export interface AuthFlowDefinition {
502
- start: AuthFlowHandler;
503
- continue: AuthFlowHandler;
504
- poll?: AuthFlowHandler;
505
- abort?: AuthFlowHandler;
1617
+ start: AuthFlowStartHandler;
1618
+ continue: AuthFlowInputHandler;
1619
+ poll?: AuthFlowStartHandler;
1620
+ abort?: AuthFlowStartHandler;
1621
+ refresh?: AuthFlowInputHandler;
1622
+ }
1623
+
1624
+ export type ProviderStateDurationString =
1625
+ | `${number}${"ms" | "s" | "m" | "h" | "d"}`
1626
+ | `PT${string}`;
1627
+
1628
+ export interface StateNamespaceOptions {
1629
+ /** Default TTL used when a write omits ttl. Required to avoid unbounded state. */
1630
+ defaultTtl: ProviderStateDurationString;
1631
+ /** Maximum allowed TTL; writes are rejected when they exceed this policy. */
1632
+ maxTtl: ProviderStateDurationString;
1633
+ /** Maximum number of live entries in this namespace scope. */
1634
+ maxEntries: number;
1635
+ /** Maximum JSON-encoded value size in bytes. */
1636
+ maxValueBytes: number;
1637
+ }
1638
+
1639
+ export interface StateWriteOptions {
1640
+ ttl?: ProviderStateDurationString;
1641
+ }
1642
+
1643
+ export interface StateValue<T = unknown> {
1644
+ key: string;
1645
+ value: T;
1646
+ version: number;
1647
+ expiresAt: string;
1648
+ createdAt: string;
1649
+ updatedAt: string;
1650
+ }
1651
+
1652
+ export type StateCasResult<T = unknown> =
1653
+ | { ok: true; value: StateValue<T> }
1654
+ | { ok: false; current: StateValue<T> | null };
1655
+
1656
+ export interface ProviderStateNamespace {
1657
+ list<T = unknown>(options?: {
1658
+ limit?: number;
1659
+ /** Optional literal key prefix used for scoped recovery scans. */
1660
+ prefix?: string;
1661
+ }): Promise<StateValue<T>[]>;
1662
+ get<T = unknown>(key: string): Promise<StateValue<T> | null>;
1663
+ set<T = unknown>(
1664
+ key: string,
1665
+ value: T,
1666
+ options?: StateWriteOptions,
1667
+ ): Promise<StateValue<T>>;
1668
+ patch<T extends Record<string, unknown>>(
1669
+ key: string,
1670
+ partial: Partial<T>,
1671
+ options?: StateWriteOptions,
1672
+ ): Promise<StateValue<T>>;
1673
+ compareAndSet<T = unknown>(
1674
+ key: string,
1675
+ expectedVersion: number,
1676
+ value: T,
1677
+ options?: StateWriteOptions,
1678
+ ): Promise<StateCasResult<T>>;
1679
+ delete(key: string): Promise<void>;
1680
+ increment(
1681
+ key: string,
1682
+ field: string,
1683
+ delta?: number,
1684
+ options?: StateWriteOptions,
1685
+ ): Promise<StateValue<Record<string, unknown>>>;
1686
+ }
1687
+
1688
+ export interface ProviderRuntimeState {
1689
+ namespace(
1690
+ name: string,
1691
+ options: StateNamespaceOptions,
1692
+ ): ProviderStateNamespace;
506
1693
  }
507
1694
 
508
1695
  export interface ProviderContext {
@@ -510,10 +1697,14 @@ export interface ProviderContext {
510
1697
  credential: CredentialContext;
511
1698
  request?: ProviderRequestContext;
512
1699
  http: HttpClient;
513
- tls: TlsClient;
1700
+ cache: ProviderCache;
1701
+ state: ProviderRuntimeState;
1702
+ stealth: StealthClient;
514
1703
  browser: BrowserClient;
515
1704
  trace: TraceContext;
516
1705
  auth: AuthContext;
1706
+ stt: SttContext;
1707
+ choice: ProviderChoiceContext;
517
1708
  }
518
1709
 
519
1710
  export interface AuthConfig {
@@ -537,29 +1728,59 @@ export interface ContextDeclaration {
537
1728
  keys: string[];
538
1729
  }
539
1730
 
1731
+ export type OperationLifecycle = "stable" | "beta" | "deprecated" | "removed";
1732
+
1733
+ export interface OperationDeprecationMetadata {
1734
+ announcedAt: string;
1735
+ removalAfter: string;
1736
+ replacement?: string;
1737
+ migrationGuide: string;
1738
+ }
1739
+
1740
+ export interface OperationContractMetadata {
1741
+ /**
1742
+ * Callable operation contract version. Defaults to 1.0.0 for the clean
1743
+ * pre-GA baseline; it intentionally does not fall back to provider.version.
1744
+ */
1745
+ version?: string;
1746
+ lifecycle?: OperationLifecycle;
1747
+ deprecation?: OperationDeprecationMetadata;
1748
+ }
1749
+
540
1750
  export interface OperationDefinition<
541
1751
  TInput extends SchemaLike = SchemaLike,
542
1752
  TOutput extends SchemaLike = SchemaLike,
543
1753
  > {
544
- description?: string;
1754
+ descriptionKey?: ProviderLocaleKeyInput;
545
1755
  docs?: OperationDocMeta;
546
- whenToUse?: string[];
547
- whenNotToUse?: string[];
1756
+ whenToUseKeys?: readonly ProviderLocaleKeyInput[];
1757
+ whenNotToUseKeys?: readonly ProviderLocaleKeyInput[];
548
1758
  derivations?: Record<string, string>;
549
- inputExamples?: OperationInputExample[];
1759
+ inputExamples?: readonly OperationInputExample[];
550
1760
  annotations?: OperationAnnotations;
551
- tags?: string[];
1761
+ contract?: OperationContractMetadata;
1762
+ tags?: readonly string[];
552
1763
  relatedOperations?: OperationRelationships;
1764
+ toolRouter?: OperationToolRouterMetadata;
1765
+ observability?: OperationObservabilityConfig;
1766
+ transport?: OperationTransport;
1767
+ retryOnAuthRefresh?: boolean;
553
1768
  input: TInput;
554
1769
  output: TOutput;
555
1770
  handler(
556
1771
  ctx: ProviderContext,
557
1772
  input: InferSchemaOutput<TInput>,
558
- ): Promise<InferSchemaOutput<TOutput>>;
1773
+ ):
1774
+ | OperationHandlerResult<InferSchemaOutput<TOutput>>
1775
+ | Promise<OperationHandlerResult<InferSchemaOutput<TOutput>>>;
559
1776
  fixtures?: {
560
1777
  request: InferSchemaOutput<TInput>;
561
1778
  response: InferSchemaOutput<TOutput>;
562
1779
  };
1780
+ upstream?: {
1781
+ baseUrl?: string;
1782
+ proxy?: boolean | ProviderProxyPolicy;
1783
+ };
563
1784
  hints?: Record<string, string>;
564
1785
  healthCheck?: HealthCheckSuite<
565
1786
  InferSchemaOutput<TInput>,
@@ -577,16 +1798,19 @@ export interface ProviderDefinition {
577
1798
  profile: string;
578
1799
  platform: StealthPlatform;
579
1800
  };
580
- proxy?: boolean;
1801
+ proxy?: ProviderProxyConfig;
1802
+ stt?: ProviderSttConfig;
581
1803
  browser?: {
582
1804
  engine: BrowserEngine;
583
1805
  };
584
1806
  auth?: AuthConfig;
585
1807
  reviewed?: ProviderReviewed;
1808
+ access?: ProviderAccessConfig;
586
1809
  secrets?: ProviderSecretDeclaration[];
587
1810
  credential?: CredentialDeclaration;
588
1811
  context?: ContextDeclaration;
589
1812
  meta: ProviderMeta;
590
1813
  operations: Record<string, OperationDefinition<SchemaLike, SchemaLike>>;
591
1814
  healthMonitor?: ProviderHealthMonitorConfig;
1815
+ healthJourneys?: readonly HealthJourneyDefinition[];
592
1816
  }