@apifuse/provider-sdk 2.2.0-beta.62 → 2.2.0-beta.64

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 (261) hide show
  1. package/AUTHORING.md +367 -9
  2. package/CHANGELOG.md +8 -0
  3. package/LICENSE +21 -0
  4. package/README.md +1 -0
  5. package/bin/apifuse-check.ts +84 -2
  6. package/bin/apifuse-dev.ts +11 -31
  7. package/bin/apifuse-migrate-deployment.ts +200 -0
  8. package/bin/apifuse-pack-check.ts +11 -4
  9. package/bin/apifuse-pack-types.ts +187 -4
  10. package/bin/apifuse-record.ts +44 -32
  11. package/bin/apifuse-submit-check.ts +9 -5
  12. package/bin/apifuse-test.ts +3 -1
  13. package/dist/cli/commands.d.ts +1 -1
  14. package/dist/cli/commands.js +11 -0
  15. package/dist/cli/deployment-intent.d.ts +178 -0
  16. package/dist/cli/deployment-intent.js +277 -0
  17. package/dist/cli/migrate-deployment-intent.d.ts +132 -0
  18. package/dist/cli/migrate-deployment-intent.js +1552 -0
  19. package/dist/cli/migrate-provider-shape.d.ts +5 -1
  20. package/dist/cli/migrate-provider-shape.js +4 -2
  21. package/dist/cli/resolver-runtime.d.ts +21 -0
  22. package/dist/cli/resolver-runtime.js +31 -0
  23. package/dist/define.d.ts +3 -0
  24. package/dist/define.js +5 -0
  25. package/dist/dev.d.ts +3 -1
  26. package/dist/dev.js +6 -1
  27. package/dist/engine.d.ts +35 -1
  28. package/dist/engine.js +21 -2
  29. package/dist/error-resolution.d.ts +1 -0
  30. package/dist/error-resolution.js +54 -0
  31. package/dist/errors.d.ts +39 -1
  32. package/dist/errors.js +50 -0
  33. package/dist/handle-meta.d.ts +36 -1
  34. package/dist/handle-meta.js +16 -0
  35. package/dist/handle.d.ts +23 -5
  36. package/dist/handle.js +54 -8
  37. package/dist/health-scenario.d.ts +38 -0
  38. package/dist/i18n/error-messages.d.ts +86 -0
  39. package/dist/i18n/error-messages.js +192 -0
  40. package/dist/i18n/index.d.ts +1 -0
  41. package/dist/i18n/index.js +1 -0
  42. package/dist/i18n/keys.d.ts +12 -0
  43. package/dist/i18n/keys.js +76 -5
  44. package/dist/index.d.ts +11 -3
  45. package/dist/index.js +9 -1
  46. package/dist/lint.d.ts +15 -0
  47. package/dist/lint.js +469 -82
  48. package/dist/provider.d.ts +6 -6
  49. package/dist/provider.js +3 -3
  50. package/dist/runtime/browser-telemetry-binding.d.ts +5 -0
  51. package/dist/runtime/browser-telemetry-binding.js +83 -0
  52. package/dist/runtime/browser-telemetry.d.ts +76 -0
  53. package/dist/runtime/browser-telemetry.js +165 -0
  54. package/dist/runtime/browser.d.ts +3 -0
  55. package/dist/runtime/browser.js +208 -47
  56. package/dist/runtime/cache-telemetry.d.ts +71 -0
  57. package/dist/runtime/cache-telemetry.js +177 -0
  58. package/dist/runtime/cache.js +67 -7
  59. package/dist/runtime/capability-response.d.ts +3 -0
  60. package/dist/runtime/capability-response.js +56 -0
  61. package/dist/runtime/capability-telemetry.d.ts +46 -0
  62. package/dist/runtime/capability-telemetry.js +68 -0
  63. package/dist/runtime/diagnostic-env.d.ts +3 -0
  64. package/dist/runtime/diagnostic-env.js +10 -1
  65. package/dist/runtime/engine-mode.d.ts +74 -0
  66. package/dist/runtime/engine-mode.js +152 -0
  67. package/dist/runtime/handle.js +9 -1
  68. package/dist/runtime/http-telemetry-guard.d.ts +10 -0
  69. package/dist/runtime/http-telemetry-guard.js +62 -10
  70. package/dist/runtime/http.js +141 -35
  71. package/dist/runtime/instrumentation.js +92 -13
  72. package/dist/runtime/ocr-telemetry.d.ts +82 -0
  73. package/dist/runtime/ocr-telemetry.js +192 -0
  74. package/dist/runtime/ocr.js +35 -8
  75. package/dist/runtime/request-telemetry.d.ts +2 -0
  76. package/dist/runtime/request-telemetry.js +2 -1
  77. package/dist/runtime/resolver-runtime-options.d.ts +14 -0
  78. package/dist/runtime/resolver-runtime-options.js +33 -0
  79. package/dist/runtime/resolver-shared.d.ts +3 -2
  80. package/dist/runtime/resolver-shared.js +4 -4
  81. package/dist/runtime/resolver-telemetry.d.ts +1 -0
  82. package/dist/runtime/resolver-telemetry.js +1 -1
  83. package/dist/runtime/resolver-vendors/browser.d.ts +2 -0
  84. package/dist/runtime/resolver-vendors/browser.js +46 -0
  85. package/dist/runtime/resolver-vendors/hosts.d.ts +21 -0
  86. package/dist/runtime/resolver-vendors/hosts.js +35 -0
  87. package/dist/runtime/resolver-vendors/hypersolutions.js +2 -2
  88. package/dist/runtime/resolver-vendors/types.d.ts +5 -4
  89. package/dist/runtime/resolver.d.ts +4 -1
  90. package/dist/runtime/resolver.js +46 -13
  91. package/dist/runtime/state-telemetry.d.ts +79 -0
  92. package/dist/runtime/state-telemetry.js +194 -0
  93. package/dist/runtime/state.d.ts +3 -0
  94. package/dist/runtime/state.js +26 -7
  95. package/dist/runtime/stealth-cookies.d.ts +5 -1
  96. package/dist/runtime/stealth-cookies.js +21 -1
  97. package/dist/runtime/stealth-owned-headers.d.ts +26 -0
  98. package/dist/runtime/stealth-owned-headers.js +37 -0
  99. package/dist/runtime/stealth-telemetry.d.ts +92 -0
  100. package/dist/runtime/stealth-telemetry.js +179 -0
  101. package/dist/runtime/stealth.d.ts +4 -1
  102. package/dist/runtime/stealth.js +228 -85
  103. package/dist/runtime/stt-telemetry.d.ts +77 -0
  104. package/dist/runtime/stt-telemetry.js +176 -0
  105. package/dist/runtime/stt.js +15 -6
  106. package/dist/runtime-boundary-lint.d.ts +132 -0
  107. package/dist/runtime-boundary-lint.js +586 -0
  108. package/dist/server/error-stack-frames.d.ts +35 -0
  109. package/dist/server/error-stack-frames.js +219 -0
  110. package/dist/server/index.d.ts +7 -0
  111. package/dist/server/index.js +4 -0
  112. package/dist/server/sdk-version.d.ts +3 -0
  113. package/dist/server/sdk-version.js +19 -0
  114. package/dist/server/self-test.js +1 -18
  115. package/dist/server/sensitive-values.d.ts +1 -1
  116. package/dist/server/sensitive-values.js +9 -0
  117. package/dist/server/serve-implementation.d.ts +51 -2
  118. package/dist/server/serve-implementation.js +337 -90
  119. package/dist/server/types.d.ts +1 -0
  120. package/dist/server/types.js +7 -0
  121. package/dist/stateful/stateful-provider-owner-forwarder.js +22 -0
  122. package/dist/stateful/stateful-provider-runtime-context.d.ts +3 -0
  123. package/dist/stateful/stateful-provider-runtime-context.js +1 -0
  124. package/dist/types.d.ts +123 -1
  125. package/dist/typescript-module.d.ts +39 -0
  126. package/dist/typescript-module.js +72 -0
  127. package/package.json +6 -1
  128. package/src/cli/commands.ts +14 -0
  129. package/src/cli/deployment-intent.ts +364 -0
  130. package/src/cli/migrate-deployment-intent.ts +1908 -0
  131. package/src/cli/migrate-provider-shape.ts +10 -4
  132. package/src/cli/resolver-runtime.ts +72 -0
  133. package/src/define.ts +13 -0
  134. package/src/dev.ts +9 -2
  135. package/src/engine.ts +38 -2
  136. package/src/error-resolution.ts +58 -0
  137. package/src/errors.ts +77 -1
  138. package/src/handle-meta.ts +51 -1
  139. package/src/handle.ts +92 -10
  140. package/src/health-scenario.ts +38 -0
  141. package/src/i18n/error-messages.ts +255 -0
  142. package/src/i18n/index.ts +1 -0
  143. package/src/i18n/keys.ts +80 -6
  144. package/src/index.ts +86 -0
  145. package/src/lint.ts +604 -91
  146. package/src/provider.ts +12 -0
  147. package/src/runtime/browser-telemetry-binding.ts +92 -0
  148. package/src/runtime/browser-telemetry.ts +289 -0
  149. package/src/runtime/browser.ts +249 -65
  150. package/src/runtime/cache-telemetry.ts +247 -0
  151. package/src/runtime/cache.ts +68 -17
  152. package/src/runtime/capability-response.ts +53 -0
  153. package/src/runtime/capability-telemetry.ts +101 -0
  154. package/src/runtime/diagnostic-env.ts +11 -1
  155. package/src/runtime/engine-mode.ts +233 -0
  156. package/src/runtime/handle.ts +9 -1
  157. package/src/runtime/http-telemetry-guard.ts +66 -13
  158. package/src/runtime/http.ts +168 -37
  159. package/src/runtime/instrumentation.ts +105 -16
  160. package/src/runtime/ocr-telemetry.ts +308 -0
  161. package/src/runtime/ocr.ts +114 -74
  162. package/src/runtime/request-telemetry.ts +2 -1
  163. package/src/runtime/resolver-runtime-options.ts +50 -0
  164. package/src/runtime/resolver-shared.ts +9 -4
  165. package/src/runtime/resolver-telemetry.ts +1 -1
  166. package/src/runtime/resolver-vendors/browser.ts +65 -7
  167. package/src/runtime/resolver-vendors/hosts.ts +43 -0
  168. package/src/runtime/resolver-vendors/hypersolutions.ts +2 -2
  169. package/src/runtime/resolver-vendors/types.ts +5 -4
  170. package/src/runtime/resolver.ts +64 -21
  171. package/src/runtime/state-telemetry.ts +298 -0
  172. package/src/runtime/state.ts +46 -45
  173. package/src/runtime/stealth-cookies.ts +24 -1
  174. package/src/runtime/stealth-owned-headers.ts +41 -0
  175. package/src/runtime/stealth-telemetry.ts +304 -0
  176. package/src/runtime/stealth.ts +355 -150
  177. package/src/runtime/stt-telemetry.ts +282 -0
  178. package/src/runtime/stt.ts +93 -71
  179. package/src/runtime-boundary-lint.ts +703 -0
  180. package/src/server/error-stack-frames.ts +214 -0
  181. package/src/server/index.ts +53 -0
  182. package/src/server/sdk-version.ts +22 -0
  183. package/src/server/self-test.ts +1 -21
  184. package/src/server/sensitive-values.ts +14 -0
  185. package/src/server/serve-implementation.ts +569 -108
  186. package/src/server/types.ts +7 -0
  187. package/src/stateful/stateful-provider-owner-forwarder.ts +23 -0
  188. package/src/stateful/stateful-provider-runtime-context.ts +4 -0
  189. package/src/types.ts +128 -1
  190. package/src/typescript-module.ts +100 -0
  191. package/src/cli/__tests__/fixtures/migrate-operation-declaration/approval-override.ts.txt +0 -6
  192. package/src/cli/__tests__/fixtures/migrate-operation-declaration/codemod-syntax.ts.txt +0 -3
  193. package/src/cli/__tests__/fixtures/migrate-operation-declaration/connection-precedence.ts.txt +0 -10
  194. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-ambiguous-a.ts.txt +0 -3
  195. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-ambiguous-b.ts.txt +0 -3
  196. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-ambiguous-barrel.ts.txt +0 -2
  197. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-ambiguous-index.ts.txt +0 -3
  198. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-computed.ts.txt +0 -6
  199. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-cycle-a.ts.txt +0 -1
  200. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-cycle-b.ts.txt +0 -1
  201. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-cycle-index.ts.txt +0 -3
  202. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-barrel.ts.txt +0 -7
  203. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-catalog.ts.txt +0 -19
  204. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-docs.ts.txt +0 -6
  205. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-index.ts.txt +0 -3
  206. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-stores.ts.txt +0 -8
  207. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-indirect-config.ts.txt +0 -5
  208. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-nonstatic.ts.txt +0 -4
  209. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-package-index.ts.txt +0 -3
  210. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-reexport-index.ts.txt +0 -3
  211. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-reexport-leaf.ts.txt +0 -10
  212. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-reexport-one.ts.txt +0 -1
  213. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-reexport-two.ts.txt +0 -1
  214. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-composed-index.ts.txt +0 -3
  215. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-composed-one.ts.txt +0 -6
  216. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-composed-two.ts.txt +0 -6
  217. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-mixed-index.ts.txt +0 -14
  218. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-registry.ts.txt +0 -3
  219. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-star-package-barrel.ts.txt +0 -2
  220. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-star-package-index.ts.txt +0 -3
  221. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-star-package-leaf.ts.txt +0 -3
  222. package/src/cli/__tests__/fixtures/migrate-operation-declaration/docs-conflict.ts.txt +0 -8
  223. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-hoisted-array-spread.ts.txt +0 -15
  224. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-imported-array-spread.ts.txt +0 -9
  225. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-kebab-operation-id.ts.txt +0 -17
  226. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-map.ts.txt +0 -5
  227. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-mixed-array-spread.ts.txt +0 -24
  228. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-operation.ts.txt +0 -16
  229. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-snake-operation-id.ts.txt +0 -21
  230. package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-duplicate-provider.ts.txt +0 -11
  231. package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-id-unresolved.ts.txt +0 -7
  232. package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-map.ts.txt +0 -3
  233. package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-one-to-many.ts.txt +0 -18
  234. package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-one-to-one.ts.txt +0 -13
  235. package/src/cli/__tests__/fixtures/migrate-operation-declaration/hoist-all.ts.txt +0 -31
  236. package/src/cli/__tests__/fixtures/migrate-operation-declaration/hoisted-const.ts.txt +0 -11
  237. package/src/cli/__tests__/fixtures/migrate-operation-declaration/imported-spread.ts.txt +0 -11
  238. package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-map.ts.txt +0 -11
  239. package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-cast-tail.ts.txt +0 -21
  240. package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-ekitan.ts.txt +0 -11
  241. package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-override.ts.txt +0 -14
  242. package/src/cli/__tests__/fixtures/migrate-operation-declaration/locale-canonical-en.json +0 -1
  243. package/src/cli/__tests__/fixtures/migrate-operation-declaration/locale-canonical-ja.json +0 -1
  244. package/src/cli/__tests__/fixtures/migrate-operation-declaration/locale-canonical-ko.json +0 -1
  245. package/src/cli/__tests__/fixtures/migrate-operation-declaration/locale-existing-operation-namespace-en.json +0 -8
  246. package/src/cli/__tests__/fixtures/migrate-operation-declaration/missing-english-locale.ts.txt +0 -7
  247. package/src/cli/__tests__/fixtures/migrate-operation-declaration/no-safety.ts.txt +0 -6
  248. package/src/cli/__tests__/fixtures/migrate-operation-declaration/non-literal.ts.txt +0 -7
  249. package/src/cli/__tests__/fixtures/migrate-operation-declaration/redundant-approval.ts.txt +0 -6
  250. package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-binding-ambiguous.ts.txt +0 -12
  251. package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-imported-other.ts.txt +0 -7
  252. package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-imported.ts.txt +0 -5
  253. package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-key-ambiguous.ts.txt +0 -19
  254. package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-shorthand.ts.txt +0 -9
  255. package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-typed.ts.txt +0 -11
  256. package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-unrelated.ts.txt +0 -13
  257. package/src/cli/__tests__/fixtures/migrate-operation-declaration/safety-conflict.ts.txt +0 -7
  258. package/src/cli/__tests__/fixtures/migrate-operation-declaration/stream.ts.txt +0 -7
  259. package/src/cli/__tests__/fixtures/migrate-operation-declaration/tool-router-spread.ts.txt +0 -15
  260. package/src/cli/__tests__/fixtures/migrate-operation-declaration/unparseable.ts.txt +0 -4
  261. package/src/cli/__tests__/fixtures/migrate-operation-declaration/verbatim-template.ts.txt +0 -12
@@ -0,0 +1,177 @@
1
+ import { Buffer } from "node:buffer";
2
+ import { closedEnum, } from "./request-telemetry.js";
3
+ import { createTelemetryObserver } from "./http-telemetry-guard.js";
4
+ const cacheTelemetryBindings = new WeakMap();
5
+ /** Internal construction binding; keeps sink plumbing off ProviderCacheOptions. */
6
+ export function bindCacheTelemetry(options, sink) {
7
+ if (sink)
8
+ cacheTelemetryBindings.set(options, sink);
9
+ return options;
10
+ }
11
+ /** Internal lookup used only by the cache factory. */
12
+ export function cacheTelemetryFor(options) {
13
+ return cacheTelemetryBindings.get(options);
14
+ }
15
+ export function guardCacheTelemetry(sink) {
16
+ const observe = createTelemetryObserver(sink);
17
+ return {
18
+ setRedisConfigured: (configured) => observe(() => sink?.setRedisConfigured?.(configured)),
19
+ recordLookup: (meta) => observe(() => sink?.recordLookup(meta)),
20
+ recordWrite: () => observe(() => sink?.recordWrite()),
21
+ recordLoaderError: () => observe(() => sink?.recordLoaderError?.()),
22
+ recordWriteError: () => observe(() => sink?.recordWriteError?.()),
23
+ recordRedisFallback: () => observe(() => sink?.recordRedisFallback()),
24
+ recordRedisRoundTrip: () => observe(() => sink?.recordRedisRoundTrip?.()),
25
+ };
26
+ }
27
+ const MAX_SAMPLES = 24;
28
+ const MAX_TEXT = 300;
29
+ function integer(value) {
30
+ return Number.isFinite(value)
31
+ ? Math.min(Number.MAX_SAFE_INTEGER, Math.max(0, Math.floor(value)))
32
+ : Number.MAX_SAFE_INTEGER;
33
+ }
34
+ function add(a, b) {
35
+ return Math.min(Number.MAX_SAFE_INTEGER, integer(a) + integer(b));
36
+ }
37
+ function boundedText(value, redact) {
38
+ let result;
39
+ try {
40
+ result = redact?.(value) ?? value;
41
+ }
42
+ catch {
43
+ result = "[REDACTION_FAILED]";
44
+ }
45
+ const length = Math.min(result.length, MAX_TEXT);
46
+ const units = Buffer.alloc(length * 2);
47
+ for (let index = 0; index < length; index += 1)
48
+ units.writeUInt16LE(result.charCodeAt(index), index * 2);
49
+ return units.toString("utf16le");
50
+ }
51
+ export class CacheTelemetryCollector {
52
+ key = "cache";
53
+ #redact;
54
+ #telemetryFailed = false;
55
+ #lookups = 0;
56
+ #hits = 0;
57
+ #stale = 0;
58
+ #misses = 0;
59
+ #writes = 0;
60
+ #loaderErrors = 0;
61
+ #writeErrors = 0;
62
+ #source = { memory: 0, redis: 0, loader: 0 };
63
+ #redisFallbacks = 0;
64
+ #configured;
65
+ #redisRoundTrips = 0;
66
+ #ages = [];
67
+ #maxAge = 0;
68
+ #samples = [];
69
+ #dropped = 0;
70
+ constructor(options = {}) {
71
+ this.#redact = options.redact;
72
+ this.#configured = "not_configured";
73
+ }
74
+ setRedisConfigured(configured) {
75
+ if (configured && this.#configured === "not_configured")
76
+ this.#configured = "configured";
77
+ }
78
+ markTelemetryFailed() {
79
+ this.#telemetryFailed = true;
80
+ }
81
+ recordLookup(meta) {
82
+ if (!["memory", "redis", "loader"].includes(meta.source)) {
83
+ this.#telemetryFailed = true;
84
+ return;
85
+ }
86
+ this.#lookups = add(this.#lookups, 1);
87
+ if (meta.hit)
88
+ this.#hits = add(this.#hits, 1);
89
+ else
90
+ this.#misses = add(this.#misses, 1);
91
+ if (meta.stale)
92
+ this.#stale = add(this.#stale, 1);
93
+ this.#source[meta.source] = add(this.#source[meta.source], 1);
94
+ if (meta.source === "redis" && this.#configured === "not_configured")
95
+ this.#configured = "configured";
96
+ if (meta.ageMs !== undefined) {
97
+ const age = integer(meta.ageMs);
98
+ if (this.#ages.length < MAX_SAMPLES)
99
+ this.#ages.push(age);
100
+ this.#maxAge = Math.max(this.#maxAge, age);
101
+ }
102
+ if (this.#samples.length < MAX_SAMPLES) {
103
+ this.#samples.push({
104
+ key: boundedText(meta.key, this.#redact),
105
+ hit: meta.hit,
106
+ stale: meta.stale,
107
+ ...(meta.ageMs === undefined ? {} : { ageMs: integer(meta.ageMs) }),
108
+ source: meta.source,
109
+ });
110
+ }
111
+ else
112
+ this.#dropped = add(this.#dropped, 1);
113
+ }
114
+ recordWrite() {
115
+ this.#writes = add(this.#writes, 1);
116
+ }
117
+ recordLoaderError() {
118
+ this.#loaderErrors = add(this.#loaderErrors, 1);
119
+ }
120
+ recordWriteError() {
121
+ this.#writeErrors = add(this.#writeErrors, 1);
122
+ }
123
+ recordRedisFallback() {
124
+ this.#redisFallbacks = add(this.#redisFallbacks, 1);
125
+ this.#configured = "degraded";
126
+ }
127
+ recordRedisRoundTrip() {
128
+ this.#redisRoundTrips = add(this.#redisRoundTrips, 1);
129
+ }
130
+ toLogPayload(_spans) {
131
+ if (this.#lookups === 0 &&
132
+ this.#writes === 0 &&
133
+ this.#redisFallbacks === 0 &&
134
+ !this.#telemetryFailed)
135
+ return undefined;
136
+ const sorted = [...this.#ages].sort((a, b) => a - b);
137
+ const p50 = sorted.length ? sorted[Math.floor((sorted.length - 1) / 2)] : undefined;
138
+ return {
139
+ ...(this.#telemetryFailed ? { telemetryFailed: true } : {}),
140
+ lookups: this.#lookups,
141
+ hits: this.#hits,
142
+ stale: this.#stale,
143
+ misses: this.#misses,
144
+ writes: this.#writes,
145
+ loaderErrors: this.#loaderErrors,
146
+ writeErrors: this.#writeErrors,
147
+ source: { ...this.#source },
148
+ redisFallbacks: this.#redisFallbacks,
149
+ redisMode: closedEnum(this.#configured),
150
+ redisRoundTrips: this.#redisRoundTrips,
151
+ ...(p50 === undefined ? {} : { ageMs: { p50, max: this.#maxAge } }),
152
+ samples: this.#samples.map((sample) => ({ ...sample })),
153
+ dropped: this.#dropped,
154
+ };
155
+ }
156
+ toHeaderPayload(log) {
157
+ return {
158
+ lookups: log.lookups,
159
+ hits: log.hits,
160
+ stale: log.stale,
161
+ misses: log.misses,
162
+ writes: log.writes,
163
+ loaderErrors: log.loaderErrors,
164
+ writeErrors: log.writeErrors,
165
+ source: {
166
+ memory: log.source.memory,
167
+ redis: log.source.redis,
168
+ loader: log.source.loader,
169
+ },
170
+ redisFallbacks: log.redisFallbacks,
171
+ redisMode: log.redisMode,
172
+ redisRoundTrips: log.redisRoundTrips,
173
+ ...(log.ageMs ? { ageP50: log.ageMs.p50, ageMax: log.ageMs.max } : {}),
174
+ dropped: log.dropped,
175
+ };
176
+ }
177
+ }
@@ -2,6 +2,7 @@ import { readDiagnosticEnv } from "./diagnostic-env.js";
2
2
  import { createHash, createHmac } from "node:crypto";
3
3
  import { providerCacheRedisUrlFromEnv } from "../config/loader.js";
4
4
  import { ProviderError } from "../errors.js";
5
+ import { cacheTelemetryFor, guardCacheTelemetry } from "./cache-telemetry.js";
5
6
  import { createProviderRedisClient, ensureRedisReady, withRedisTimeout, } from "./redis.js";
6
7
  export const APIFUSE__CACHE__KEY_PEPPER_ENV = "APIFUSE__CACHE__KEY_PEPPER";
7
8
  const DEFAULT_PREFIX = "apifuse:provider-cache:v1";
@@ -286,9 +287,13 @@ export function createProviderCache(options) {
286
287
  const memoryMaxEntries = Math.max(1, options.memoryMaxEntries ?? DEFAULT_MEMORY_MAX_ENTRIES);
287
288
  const now = options.now ?? Date.now;
288
289
  const events = [];
290
+ const telemetry = guardCacheTelemetry(cacheTelemetryFor(options));
291
+ telemetry.setRedisConfigured?.(!!redisUrl);
292
+ let redisUnavailable = false;
289
293
  const secretScopedKeys = new Set();
290
294
  function record(meta) {
291
295
  events.push(meta);
296
+ telemetry?.recordLookup(meta);
292
297
  }
293
298
  function sweepMemory(currentTime) {
294
299
  for (const [entryKey, entry] of backend.memory) {
@@ -322,13 +327,21 @@ export function createProviderCache(options) {
322
327
  async function readRedis(key, currentTime) {
323
328
  const redis = backend.redis;
324
329
  if (!redis || !(await ensureRedisReady(redis, DEFAULT_REDIS_TIMEOUT_MS))) {
330
+ if (redis) {
331
+ redisUnavailable = true;
332
+ telemetry?.recordRedisFallback();
333
+ }
325
334
  return null;
326
335
  }
327
336
  const raw = await withRedisFallback(async () => {
328
337
  return await redis.get(key);
329
338
  });
330
- if (typeof raw !== "string" && raw !== null)
339
+ if (typeof raw !== "string" && raw !== null) {
340
+ redisUnavailable = true;
341
+ telemetry.recordRedisFallback();
331
342
  return null;
343
+ }
344
+ telemetry?.recordRedisRoundTrip?.();
332
345
  const envelope = safeParseEnvelope(raw);
333
346
  if (!envelope)
334
347
  return null;
@@ -370,6 +383,7 @@ export function createProviderCache(options) {
370
383
  return staleMemoryResult;
371
384
  }
372
385
  async function write(key, value, cacheOptions) {
386
+ telemetry?.recordWrite();
373
387
  const currentTime = now();
374
388
  const freshTtlMs = jitteredTtlMs(cacheOptions.ttlMs, cacheOptions.jitterPct);
375
389
  const staleIfErrorMs = cacheOptions.staleIfErrorMs ?? 0;
@@ -383,9 +397,21 @@ export function createProviderCache(options) {
383
397
  rememberEnvelope(key, envelope, currentTime);
384
398
  const redis = backend.redis;
385
399
  if (!redis || !(await ensureRedisReady(redis, DEFAULT_REDIS_TIMEOUT_MS))) {
400
+ if (redis) {
401
+ redisUnavailable = true;
402
+ telemetry?.recordRedisFallback();
403
+ telemetry?.recordWriteError?.();
404
+ }
386
405
  return;
387
406
  }
388
- await withRedisFallback(() => redis.set(key, JSON.stringify(envelope), "PX", staleTtlMs));
407
+ const written = await withRedisFallback(() => redis.set(key, JSON.stringify(envelope), "PX", staleTtlMs));
408
+ if (written === undefined) {
409
+ redisUnavailable = true;
410
+ telemetry?.recordRedisFallback();
411
+ telemetry?.recordWriteError?.();
412
+ }
413
+ else
414
+ telemetry?.recordRedisRoundTrip?.();
389
415
  }
390
416
  async function loadAndStore(key, loader, cacheOptions, staleCandidate) {
391
417
  try {
@@ -405,6 +431,13 @@ export function createProviderCache(options) {
405
431
  if (staleCandidate?.meta.stale) {
406
432
  return staleCandidate;
407
433
  }
434
+ telemetry?.recordLookup({
435
+ key,
436
+ hit: false,
437
+ stale: false,
438
+ source: "loader",
439
+ });
440
+ telemetry?.recordLoaderError?.();
408
441
  throw error;
409
442
  }
410
443
  }
@@ -421,16 +454,30 @@ export function createProviderCache(options) {
421
454
  const result = await read(key);
422
455
  if (result)
423
456
  record(result.meta);
457
+ else
458
+ telemetry.recordLookup({
459
+ key,
460
+ hit: false,
461
+ stale: false,
462
+ source: backend.redis && !redisUnavailable ? "redis" : "memory",
463
+ });
424
464
  return result;
425
465
  },
426
466
  set: write,
427
467
  async delete(key) {
468
+ telemetry?.recordWrite();
428
469
  backend.memory.delete(key);
429
470
  const redis = backend.redis;
430
471
  if (!redis || !(await ensureRedisReady(redis, DEFAULT_REDIS_TIMEOUT_MS))) {
472
+ if (redis)
473
+ telemetry?.recordRedisFallback();
431
474
  return;
432
475
  }
433
- await withRedisFallback(() => redis.del(key));
476
+ const deleted = await withRedisFallback(() => redis.del(key));
477
+ if (deleted === undefined)
478
+ telemetry?.recordRedisFallback();
479
+ else
480
+ telemetry?.recordRedisRoundTrip?.();
434
481
  },
435
482
  async getOrSet(key, loader, cacheOptions) {
436
483
  const existing = await read(key);
@@ -440,10 +487,23 @@ export function createProviderCache(options) {
440
487
  }
441
488
  const existingInflight = backend.inflight.get(key);
442
489
  if (existingInflight) {
443
- const inflightResult = await existingInflight;
444
- const result = resultWithValue(inflightResult.value, inflightResult.meta);
445
- record(result.meta);
446
- return result;
490
+ try {
491
+ const inflightResult = await existingInflight;
492
+ const result = resultWithValue(inflightResult.value, inflightResult.meta);
493
+ record(result.meta);
494
+ return result;
495
+ }
496
+ catch (error) {
497
+ const meta = {
498
+ key,
499
+ hit: false,
500
+ stale: false,
501
+ source: "loader",
502
+ };
503
+ telemetry.recordLookup(meta);
504
+ telemetry?.recordLoaderError?.();
505
+ throw error;
506
+ }
447
507
  }
448
508
  const promise = loadAndStore(key, loader, cacheOptions, existing).finally(() => {
449
509
  backend.inflight.delete(key);
@@ -0,0 +1,3 @@
1
+ export declare const CAPABILITY_BODY_UNAVAILABLE = "<body unavailable>";
2
+ /** Read optional diagnostic response text without letting a body stall the request failure. */
3
+ export declare function readCapabilityErrorBody(response: Response, signal: AbortSignal): Promise<string>;
@@ -0,0 +1,56 @@
1
+ export const CAPABILITY_BODY_UNAVAILABLE = "<body unavailable>";
2
+ /** Read optional diagnostic response text without letting a body stall the request failure. */
3
+ export async function readCapabilityErrorBody(response, signal) {
4
+ if (signal.aborted)
5
+ return CAPABILITY_BODY_UNAVAILABLE;
6
+ let timer;
7
+ let onAbort;
8
+ let reader;
9
+ let unavailableWon = false;
10
+ const cancelBody = (reason) => {
11
+ const cancellation = reader ? reader.cancel(reason) : response.body?.cancel(reason);
12
+ if (cancellation)
13
+ void cancellation.catch(() => { });
14
+ };
15
+ const unavailable = new Promise((resolve) => {
16
+ onAbort = () => {
17
+ unavailableWon = true;
18
+ resolve(CAPABILITY_BODY_UNAVAILABLE);
19
+ cancelBody(signal.reason);
20
+ };
21
+ signal.addEventListener("abort", onAbort, { once: true });
22
+ timer = setTimeout(() => {
23
+ unavailableWon = true;
24
+ resolve(CAPABILITY_BODY_UNAVAILABLE);
25
+ cancelBody(new Error("capability error body read timeout"));
26
+ }, 250);
27
+ });
28
+ const body = Promise.resolve()
29
+ .then(async () => {
30
+ if (unavailableWon)
31
+ return CAPABILITY_BODY_UNAVAILABLE;
32
+ if (!response.body)
33
+ return response.text();
34
+ reader = response.body.getReader();
35
+ const decoder = new TextDecoder();
36
+ let text = "";
37
+ while (true) {
38
+ if (unavailableWon)
39
+ return CAPABILITY_BODY_UNAVAILABLE;
40
+ const chunk = await reader.read();
41
+ if (chunk.done)
42
+ return text + decoder.decode();
43
+ text += decoder.decode(chunk.value, { stream: true });
44
+ }
45
+ })
46
+ .catch(() => CAPABILITY_BODY_UNAVAILABLE);
47
+ try {
48
+ return await Promise.race([body, unavailable]);
49
+ }
50
+ finally {
51
+ if (timer !== undefined)
52
+ clearTimeout(timer);
53
+ if (onAbort)
54
+ signal.removeEventListener("abort", onAbort);
55
+ }
56
+ }
@@ -0,0 +1,46 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+ /** Internal capture facts, isolated across concurrent calls and never attached to caller results. */
3
+ export type CapabilityFacts = {
4
+ status?: number;
5
+ finishReason?: string;
6
+ diagnostics?: string;
7
+ };
8
+ export declare const capabilityFacts: AsyncLocalStorage<CapabilityFacts>;
9
+ export declare function tagCapability<T extends object>(context: T, facts: {
10
+ backend: string;
11
+ engine: string;
12
+ model?: string;
13
+ }): T;
14
+ export declare function capabilityMetadata(context: object): {
15
+ backend: string;
16
+ engine: string;
17
+ model?: string;
18
+ } | undefined;
19
+ export declare function captureCapability(facts: CapabilityFacts): void;
20
+ export declare function registerCapabilityInput(input: {
21
+ kind: string;
22
+ data?: string;
23
+ url?: string;
24
+ }): void;
25
+ /**
26
+ * Formats capability diagnostics after credential redaction.
27
+ * When `stripPayload` is enabled, long base64-shaped runs are replaced as a
28
+ * defence in depth; this may replace an unregistered long identifier, while
29
+ * protecting against the more likely case of payload data in an upstream body.
30
+ */
31
+ export declare function capabilityText(value: string, redact?: (text: string) => string, stripPayload?: boolean): string;
32
+ export declare function capabilityErrorText(error: unknown): string;
33
+ export declare const integer: (n: number | undefined) => number;
34
+ export declare const add: (a: number, b: number) => number;
35
+ export declare function inputBytes(input: {
36
+ kind: string;
37
+ data?: string;
38
+ }): number | undefined;
39
+ /** All capability hooks use the HTTP observer guard, including failure reporting. */
40
+ export declare function observeCapability(sink: {
41
+ markTelemetryFailed?(): void;
42
+ }, callback: () => unknown): void;
43
+ type RootRunner = <T>(callback: () => Promise<T>) => Promise<T>;
44
+ export declare function bindCapabilityRoot<T extends object>(context: T, run: RootRunner): T;
45
+ export declare function runCapabilitySpan<T>(context: object, callback: () => Promise<T>): Promise<T>;
46
+ export {};
@@ -0,0 +1,68 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+ import { Buffer } from "node:buffer";
3
+ import { registerDiagnosticValue } from "./diagnostic-env.js";
4
+ import { redactDiagnosticText } from "./diagnostic-redactor.js";
5
+ import { observeTelemetry } from "./http-telemetry-guard.js";
6
+ import { boundedText } from "./resolver-telemetry.js";
7
+ export const capabilityFacts = new AsyncLocalStorage();
8
+ const metadata = new WeakMap();
9
+ export function tagCapability(context, facts) {
10
+ metadata.set(context, facts);
11
+ return context;
12
+ }
13
+ export function capabilityMetadata(context) {
14
+ return metadata.get(context);
15
+ }
16
+ export function captureCapability(facts) {
17
+ const current = capabilityFacts.getStore();
18
+ if (current)
19
+ Object.assign(current, facts);
20
+ }
21
+ export function registerCapabilityInput(input) {
22
+ // Payloads are measurements, never redaction needles. Only bounded URLs belong
23
+ // in the request inventory; structural stripping covers oversized URL echoes.
24
+ if (input.kind === "url" && input.url && Buffer.byteLength(input.url) <= 2048)
25
+ registerDiagnosticValue(input.url.trim());
26
+ }
27
+ /**
28
+ * Formats capability diagnostics after credential redaction.
29
+ * When `stripPayload` is enabled, long base64-shaped runs are replaced as a
30
+ * defence in depth; this may replace an unregistered long identifier, while
31
+ * protecting against the more likely case of payload data in an upstream body.
32
+ */
33
+ export function capabilityText(value, redact, stripPayload = false) {
34
+ const stripped = value
35
+ .replace(/(?:authorization|proxy-authorization|cookie|set-cookie)\s*["']?\s*[:=]\s*[^\r\n]+/gi, "[REDACTED]")
36
+ .replace(/Bearer\s+[^\r\n]+/gi, "[REDACTED]")
37
+ .replace(/https?:\/\/[^\s"'<>]+/gi, "[REDACTED]")
38
+ .replace(/data:[^\s"']+/gi, "[BASE64_STRIPPED]");
39
+ return boundedText(stripPayload ? stripped.replace(/[A-Za-z0-9+/=]{64,}/g, "[BASE64_STRIPPED]") : stripped, (text) => redactDiagnosticText(text, redact));
40
+ }
41
+ export function capabilityErrorText(error) {
42
+ if (!(error instanceof Error))
43
+ return String(error);
44
+ const details = "details" in error ? error.details : undefined;
45
+ const body = details && typeof details === "object" && "body" in details ? details.body : undefined;
46
+ return `${error.message}${typeof body === "string" ? ` ${body}` : ""}`;
47
+ }
48
+ export const integer = (n) => Math.min(Number.MAX_SAFE_INTEGER, Math.max(0, Math.floor(Number.isFinite(n ?? 0) ? (n ?? 0) : 0)));
49
+ export const add = (a, b) => Math.min(Number.MAX_SAFE_INTEGER, integer(a) + integer(b));
50
+ export function inputBytes(input) {
51
+ if (input.kind !== "base64" || input.data === undefined)
52
+ return undefined;
53
+ return Buffer.byteLength(input.data.trim(), "base64");
54
+ }
55
+ /** All capability hooks use the HTTP observer guard, including failure reporting. */
56
+ export function observeCapability(sink, callback) {
57
+ observeTelemetry(callback, () => {
58
+ observeTelemetry(() => sink.markTelemetryFailed?.(), () => { });
59
+ });
60
+ }
61
+ const roots = new WeakMap();
62
+ export function bindCapabilityRoot(context, run) {
63
+ roots.set(context, run);
64
+ return context;
65
+ }
66
+ export function runCapabilitySpan(context, callback) {
67
+ return roots.get(context)?.(callback) ?? callback();
68
+ }
@@ -4,8 +4,11 @@ export interface DiagnosticEnvScope {
4
4
  observe: EnvObserver;
5
5
  finished: boolean;
6
6
  staticValues?: CompiledDiagnosticSensitiveValues;
7
+ register?: (values: readonly string[]) => void;
7
8
  }
8
9
  /** Resolve and register atomically, before any consumer can use a live env credential. */
9
10
  export declare function readDiagnosticEnv(name: string, env?: Readonly<Record<string, string | undefined>>): string | undefined;
11
+ /** Register a runtime-discovered sensitive value in the active request inventory. */
12
+ export declare function registerDiagnosticValue(value: string): void;
10
13
  export declare function withDiagnosticEnv<T>(observer: EnvObserver | DiagnosticEnvScope, fn: () => T): T;
11
14
  export {};
@@ -1,5 +1,5 @@
1
1
  import { AsyncLocalStorage } from "node:async_hooks";
2
- import { resolvedStringVariants, urlCredentialComponents, otlpHeaderCredentialValues, } from "./diagnostic-env-values.js";
2
+ import { otlpHeaderCredentialValues, resolvedStringVariants, urlCredentialComponents, } from "./diagnostic-env-values.js";
3
3
  import { registerProcessDiagnosticValues, suppressProcessDiagnosticValues, withAppDiagnosticFallback, } from "./diagnostic-redactor.js";
4
4
  const observers = new AsyncLocalStorage();
5
5
  /** Resolve and register atomically, before any consumer can use a live env credential. */
@@ -28,6 +28,15 @@ export function readDiagnosticEnv(name, env = process.env) {
28
28
  }
29
29
  return value;
30
30
  }
31
+ /** Register a runtime-discovered sensitive value in the active request inventory. */
32
+ export function registerDiagnosticValue(value) {
33
+ if (value.length < 4)
34
+ return;
35
+ const scope = observers.getStore();
36
+ if (scope && !scope.finished && scope.register) {
37
+ scope.register([value]);
38
+ }
39
+ }
31
40
  export function withDiagnosticEnv(observer, fn) {
32
41
  const scope = typeof observer === "function" ? { observe: observer, finished: false } : observer;
33
42
  const run = () => observers.run(scope, fn);
@@ -0,0 +1,74 @@
1
+ import { type ProviderEngine, type ProviderEngineMode } from "../engine.js";
2
+ /** Mode used when neither `engineMode` nor `APIFUSE__ENGINE__MODE` names one. */
3
+ export declare const DEFAULT_PROVIDER_ENGINE_MODE = "in-process";
4
+ /** Remote engine client endpoint; engine-owned, so never declarable as a provider secret. */
5
+ export declare const REMOTE_ENGINE_CLIENT_URL_ENV = "APIFUSE__ENGINE__URL";
6
+ /** Remote engine client credential; registered with the diagnostic redactor by sensitive-values. */
7
+ export declare const REMOTE_ENGINE_CLIENT_API_KEY_ENV = "APIFUSE__ENGINE__API_KEY";
8
+ /** Where the resolved mode came from, in precedence order. */
9
+ export type ProviderEngineModeSource = "engine" | "env" | "option" | "default";
10
+ /**
11
+ * Non-fatal conditions worth reporting at boot:
12
+ * - `invalid_env_value`: `APIFUSE__ENGINE__MODE` held an unrecognized value.
13
+ * - `env_overrode_option`: the manifest and the host code disagreed; the manifest won.
14
+ * - `engine_object_overrode_requested_mode`: an explicit engine object cannot honour the requested mode.
15
+ * - `engine_env_ignored`: remote-only engine env is projected but the mode is not
16
+ * remote (not reported for a host-supplied engine, which may consume it itself).
17
+ */
18
+ export type ProviderEngineModeWarning = "invalid_env_value" | "env_overrode_option" | "engine_object_overrode_requested_mode" | "engine_env_ignored";
19
+ export interface ProviderEngineModeResolution {
20
+ readonly mode: ProviderEngineMode | "custom";
21
+ readonly source: ProviderEngineModeSource;
22
+ /** True for every non-remote attachment, whose removal is scheduled by ADR-0011. */
23
+ readonly deprecated: boolean;
24
+ readonly warnings: readonly ProviderEngineModeWarning[];
25
+ }
26
+ export interface ProviderEngineModeResolutionInput {
27
+ /** Explicit `engineMode` option passed by the host process. */
28
+ readonly option?: ProviderEngineMode;
29
+ /** Explicit engine object passed by the host; used as given when present. */
30
+ readonly engine?: Pick<ProviderEngine, "kind">;
31
+ /** Environment to read the engine env from; defaults to `process.env`. */
32
+ readonly environment?: Readonly<Record<string, string | undefined>>;
33
+ }
34
+ /**
35
+ * Resolve the engine attachment mode once at boot.
36
+ *
37
+ * Precedence: an explicit `engine` object, then `APIFUSE__ENGINE__MODE`, then the
38
+ * `engineMode` option, then the default. The manifest outranks the option so
39
+ * provider code cannot silently downgrade what the deployment asked for; every
40
+ * disagreement is reported in `warnings` with a truthful `source` rather than
41
+ * being dropped.
42
+ *
43
+ * Deployment-authored input is never fatal (an unrecognized env value is warned
44
+ * about and ignored). A malformed `engineMode` option is a fault in the calling
45
+ * code, which no manifest can reach, so it throws.
46
+ */
47
+ export declare function resolveProviderEngineMode(input?: ProviderEngineModeResolutionInput): ProviderEngineModeResolution;
48
+ /** True when the engine cannot attach, so readiness must report the process as unready. */
49
+ export declare function isUnavailableProviderEngine(engine: ProviderEngine): boolean;
50
+ /**
51
+ * Engine that refuses every attachment with `reason`.
52
+ *
53
+ * Requesting a mode this release cannot serve must not crash the process: the SDK
54
+ * answers a structured error per request and reports the process unready, the same
55
+ * trade-off `provider_secrets_missing` already makes at boot. Non-retryable, so a
56
+ * caller-side retry loop cannot turn a configuration fault into load.
57
+ */
58
+ export declare function createUnavailableProviderEngine(kind: ProviderEngineMode, reason: {
59
+ message: string;
60
+ code: string;
61
+ fix: string;
62
+ }): ProviderEngine;
63
+ /**
64
+ * Engine for a resolved mode. `remote` has no client in this release, so it
65
+ * resolves to an engine that fails every request instead of falling back to
66
+ * in-process (ADR-0011 Pitfall 2: in-process is never a fallback).
67
+ */
68
+ export declare function createEngineForMode(mode: ProviderEngineMode | "custom"): ProviderEngine;
69
+ /**
70
+ * Fail fast for the CLIs (`apifuse dev`, `apifuse record`). They are developer
71
+ * tools, not pods: an unusable mode should stop the command rather than start a
72
+ * server that refuses every request.
73
+ */
74
+ export declare function assertProcessEngineModeSupported(environment?: Readonly<Record<string, string | undefined>>): ProviderEngineModeResolution;