@apifuse/provider-sdk 2.2.0-beta.5 → 2.2.0-beta.51

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 (368) hide show
  1. package/AUTHORING.md +537 -33
  2. package/CHANGELOG.md +205 -1
  3. package/README.md +83 -22
  4. package/SUBMISSION.md +2 -2
  5. package/bin/apifuse-check.ts +165 -11
  6. package/bin/apifuse-dev.ts +57 -13
  7. package/bin/apifuse-migrate-operation-declaration.ts +55 -0
  8. package/bin/apifuse-migrate-shape.ts +202 -0
  9. package/bin/apifuse-pack-check.ts +22 -2
  10. package/bin/apifuse-pack-smoke.ts +57 -2
  11. package/bin/apifuse-pack-types.ts +357 -38
  12. package/bin/apifuse-perf.ts +14 -13
  13. package/bin/apifuse-record.ts +709 -72
  14. package/bin/apifuse-submit-check.ts +2344 -324
  15. package/bin/apifuse-sync-assets.ts +117 -0
  16. package/bin/submit-check-delimited-text.ts +50 -0
  17. package/dist/auth-turn/index.d.ts +3 -3
  18. package/dist/auth-turn/index.js +1 -1
  19. package/dist/auth.d.ts +14 -0
  20. package/dist/auth.js +67 -0
  21. package/dist/ceremonies/index.d.ts +16 -0
  22. package/dist/ceremonies/index.js +141 -36
  23. package/dist/cli/commands.d.ts +1 -1
  24. package/dist/cli/commands.js +27 -0
  25. package/dist/cli/create.d.ts +4 -1
  26. package/dist/cli/create.js +42 -37
  27. package/dist/cli/migrate-operation-declaration.d.ts +59 -0
  28. package/dist/cli/migrate-operation-declaration.js +1249 -0
  29. package/dist/cli/migrate-operation-shape.d.ts +44 -0
  30. package/dist/cli/migrate-operation-shape.js +113 -0
  31. package/dist/cli/migrate-provider-shape.d.ts +52 -0
  32. package/dist/cli/migrate-provider-shape.js +578 -0
  33. package/dist/cli/prompt-assets.d.ts +80 -0
  34. package/dist/cli/prompt-assets.js +743 -0
  35. package/dist/cli/templates/provider/AGENTS.md.tpl +17 -8
  36. package/dist/cli/templates/provider/Dockerfile.tpl +1 -1
  37. package/dist/cli/templates/provider/README.md.tpl +5 -5
  38. package/dist/cli/templates/provider/index.ts.tpl +6 -3
  39. package/dist/cli/templates/provider/operations/ping.ts.tpl +4 -1
  40. package/dist/cli/templates/provider/provider.json.tpl +6 -0
  41. package/dist/config/loader.d.ts +179 -16
  42. package/dist/config/loader.js +435 -127
  43. package/dist/contract-serialization.js +4 -8
  44. package/dist/contract-types.d.ts +12 -5
  45. package/dist/contract.js +24 -10
  46. package/dist/declaration-validation.d.ts +33 -0
  47. package/dist/declaration-validation.js +266 -0
  48. package/dist/define.d.ts +66 -29
  49. package/dist/define.js +778 -69
  50. package/dist/dev.d.ts +3 -0
  51. package/dist/dev.js +1 -1
  52. package/dist/engine.d.ts +78 -0
  53. package/dist/engine.js +133 -0
  54. package/dist/error-observability.d.ts +7 -0
  55. package/dist/error-observability.js +61 -0
  56. package/dist/error-resolution.d.ts +4 -0
  57. package/dist/error-resolution.js +122 -0
  58. package/dist/errors.d.ts +33 -0
  59. package/dist/errors.js +40 -0
  60. package/dist/fixture-sanitization.d.ts +28 -0
  61. package/dist/fixture-sanitization.js +227 -0
  62. package/dist/health-scenario.d.ts +1842 -0
  63. package/dist/health-scenario.js +624 -0
  64. package/dist/index.d.ts +21 -10
  65. package/dist/index.js +12 -7
  66. package/dist/lint.d.ts +23 -11
  67. package/dist/lint.js +572 -69
  68. package/dist/native-address.d.ts +43 -0
  69. package/dist/native-address.js +281 -0
  70. package/dist/native-egress-policy.d.ts +31 -0
  71. package/dist/native-egress-policy.js +288 -0
  72. package/dist/observability.d.ts +5 -2
  73. package/dist/observability.js +48 -1
  74. package/dist/provider.d.ts +10 -2
  75. package/dist/provider.js +4 -1
  76. package/dist/runtime/auth-flow.d.ts +5 -1
  77. package/dist/runtime/auth-flow.js +6 -0
  78. package/dist/runtime/browser.d.ts +1 -0
  79. package/dist/runtime/browser.js +492 -49
  80. package/dist/runtime/cache.d.ts +1 -0
  81. package/dist/runtime/cache.js +169 -15
  82. package/dist/runtime/choice-wordlist.d.ts +9 -0
  83. package/dist/runtime/choice-wordlist.js +138 -0
  84. package/dist/runtime/choice.d.ts +13 -1
  85. package/dist/runtime/choice.js +490 -102
  86. package/dist/runtime/chrome149-header-order.d.ts +58 -0
  87. package/dist/runtime/chrome149-header-order.js +289 -0
  88. package/dist/runtime/env.js +12 -0
  89. package/dist/runtime/executor.d.ts +3 -2
  90. package/dist/runtime/executor.js +26 -25
  91. package/dist/runtime/http.d.ts +1 -0
  92. package/dist/runtime/http.js +515 -53
  93. package/dist/runtime/insights.js +2 -2
  94. package/dist/runtime/instrumentation.d.ts +2 -2
  95. package/dist/runtime/instrumentation.js +366 -8
  96. package/dist/runtime/native-network-errors.d.ts +33 -0
  97. package/dist/runtime/native-network-errors.js +69 -0
  98. package/dist/runtime/native-network.d.ts +96 -0
  99. package/dist/runtime/native-network.js +1232 -0
  100. package/dist/runtime/ocr.d.ts +29 -0
  101. package/dist/runtime/ocr.js +440 -0
  102. package/dist/runtime/otlp.d.ts +71 -2
  103. package/dist/runtime/otlp.js +397 -16
  104. package/dist/runtime/proxy-errors.js +6 -2
  105. package/dist/runtime/proxy-nodemaven.d.ts +56 -0
  106. package/dist/runtime/proxy-nodemaven.js +146 -0
  107. package/dist/runtime/proxy-telemetry.d.ts +80 -1
  108. package/dist/runtime/proxy-telemetry.js +154 -47
  109. package/dist/runtime/redirects.d.ts +29 -0
  110. package/dist/runtime/redirects.js +36 -0
  111. package/dist/runtime/redis.d.ts +1 -1
  112. package/dist/runtime/redis.js +4 -2
  113. package/dist/runtime/request-options.d.ts +68 -1
  114. package/dist/runtime/request-options.js +548 -0
  115. package/dist/runtime/resolver-config.d.ts +6 -0
  116. package/dist/runtime/resolver-config.js +6 -0
  117. package/dist/runtime/resolver-public.d.ts +1 -0
  118. package/dist/runtime/resolver-public.js +1 -0
  119. package/dist/runtime/resolver-shared.d.ts +14 -0
  120. package/dist/runtime/resolver-shared.js +12 -0
  121. package/dist/runtime/resolver-vendors/bindings.d.ts +48 -0
  122. package/dist/runtime/resolver-vendors/bindings.js +40 -0
  123. package/dist/runtime/resolver-vendors/browser.d.ts +22 -0
  124. package/dist/runtime/resolver-vendors/browser.js +377 -0
  125. package/dist/runtime/resolver-vendors/capsolver.d.ts +22 -0
  126. package/dist/runtime/resolver-vendors/capsolver.js +531 -0
  127. package/dist/runtime/resolver-vendors/hosts.d.ts +2 -0
  128. package/dist/runtime/resolver-vendors/hosts.js +33 -0
  129. package/dist/runtime/resolver-vendors/twocaptcha.d.ts +24 -0
  130. package/dist/runtime/resolver-vendors/twocaptcha.js +408 -0
  131. package/dist/runtime/resolver-vendors/types.d.ts +94 -0
  132. package/dist/runtime/resolver-vendors/types.js +96 -0
  133. package/dist/runtime/resolver.d.ts +72 -0
  134. package/dist/runtime/resolver.js +771 -0
  135. package/dist/runtime/secrets.d.ts +27 -0
  136. package/dist/runtime/secrets.js +51 -0
  137. package/dist/runtime/state.d.ts +3 -0
  138. package/dist/runtime/state.js +277 -71
  139. package/dist/runtime/stealth-cookies.d.ts +20 -0
  140. package/dist/runtime/stealth-cookies.js +111 -0
  141. package/dist/runtime/stealth.d.ts +41 -5
  142. package/dist/runtime/stealth.js +997 -291
  143. package/dist/runtime/stt.js +1 -12
  144. package/dist/runtime/timeout.d.ts +5 -0
  145. package/dist/runtime/timeout.js +12 -0
  146. package/dist/runtime/trace-config.d.ts +12 -0
  147. package/dist/runtime/trace-config.js +62 -0
  148. package/dist/runtime/trace.d.ts +5 -0
  149. package/dist/runtime/trace.js +43 -10
  150. package/dist/serve.d.ts +1 -1
  151. package/dist/serve.js +1 -1
  152. package/dist/server/error-observability.d.ts +1 -0
  153. package/dist/server/error-observability.js +1 -0
  154. package/dist/server/index.d.ts +5 -2
  155. package/dist/server/index.js +2 -2
  156. package/dist/server/self-test-input-tokens.d.ts +2 -1
  157. package/dist/server/self-test-input-tokens.js +18 -14
  158. package/dist/server/self-test.d.ts +14 -3
  159. package/dist/server/self-test.js +129 -58
  160. package/dist/server/serve-implementation.d.ts +230 -0
  161. package/dist/server/serve-implementation.js +2265 -0
  162. package/dist/server/serve.d.ts +1 -70
  163. package/dist/server/serve.js +1 -1131
  164. package/dist/server/trace-output.d.ts +6 -0
  165. package/dist/server/trace-output.js +79 -0
  166. package/dist/server/types.d.ts +30 -5
  167. package/dist/server/types.js +13 -1
  168. package/dist/stateful/errors.d.ts +19 -0
  169. package/dist/stateful/errors.js +24 -0
  170. package/dist/stateful/http-provider-event-emitter.d.ts +40 -0
  171. package/dist/stateful/http-provider-event-emitter.js +237 -0
  172. package/dist/stateful/http-session-owner-registry.d.ts +44 -0
  173. package/dist/stateful/http-session-owner-registry.js +210 -0
  174. package/dist/stateful/index.d.ts +18 -0
  175. package/dist/stateful/index.js +18 -0
  176. package/dist/stateful/provider-event-delivery-failures.d.ts +32 -0
  177. package/dist/stateful/provider-event-delivery-failures.js +43 -0
  178. package/dist/stateful/provider-event-pipeline-metrics.d.ts +46 -0
  179. package/dist/stateful/provider-event-pipeline-metrics.js +48 -0
  180. package/dist/stateful/provider-event-pipeline.d.ts +50 -0
  181. package/dist/stateful/provider-event-pipeline.js +1 -0
  182. package/dist/stateful/provider-events.d.ts +101 -0
  183. package/dist/stateful/provider-events.js +289 -0
  184. package/dist/stateful/session-key.d.ts +15 -0
  185. package/dist/stateful/session-key.js +86 -0
  186. package/dist/stateful/stateful-provider-adapter-context.d.ts +5 -0
  187. package/dist/stateful/stateful-provider-adapter-context.js +42 -0
  188. package/dist/stateful/stateful-provider-adapter-metrics.d.ts +15 -0
  189. package/dist/stateful/stateful-provider-adapter-metrics.js +21 -0
  190. package/dist/stateful/stateful-provider-adapter.d.ts +98 -0
  191. package/dist/stateful/stateful-provider-adapter.js +287 -0
  192. package/dist/stateful/stateful-provider-observability.d.ts +62 -0
  193. package/dist/stateful/stateful-provider-observability.js +161 -0
  194. package/dist/stateful/stateful-provider-owner-forwarder.d.ts +41 -0
  195. package/dist/stateful/stateful-provider-owner-forwarder.js +215 -0
  196. package/dist/stateful/stateful-provider-runtime-context.d.ts +32 -0
  197. package/dist/stateful/stateful-provider-runtime-context.js +60 -0
  198. package/dist/stateful/stateful-provider-runtime-executor.d.ts +34 -0
  199. package/dist/stateful/stateful-provider-runtime-executor.js +52 -0
  200. package/dist/stateful/stateful-provider-session-routing.d.ts +67 -0
  201. package/dist/stateful/stateful-provider-session-routing.js +345 -0
  202. package/dist/stateful/stateful-provider-session-runtime.d.ts +98 -0
  203. package/dist/stateful/stateful-provider-session-runtime.js +245 -0
  204. package/dist/stateful-signing.d.ts +18 -0
  205. package/dist/stateful-signing.js +27 -0
  206. package/dist/stealth/profiles.d.ts +9 -4
  207. package/dist/stealth/profiles.js +160 -211
  208. package/dist/stream-evidence.d.ts +74 -0
  209. package/dist/stream-evidence.js +785 -0
  210. package/dist/stream.js +7 -1
  211. package/dist/testing/index.d.ts +2 -1
  212. package/dist/testing/index.js +2 -1
  213. package/dist/testing/run.d.ts +32 -2
  214. package/dist/testing/run.js +489 -21
  215. package/dist/trace-sanitization.d.ts +5 -0
  216. package/dist/trace-sanitization.js +45 -0
  217. package/dist/types.d.ts +673 -131
  218. package/dist/types.js +1 -0
  219. package/package.json +45 -5
  220. package/src/auth-turn/index.ts +1 -1
  221. package/src/auth.ts +118 -0
  222. package/src/ceremonies/index.ts +189 -46
  223. package/src/cli/__tests__/fixtures/migrate-operation-declaration/approval-override.ts.txt +6 -0
  224. package/src/cli/__tests__/fixtures/migrate-operation-declaration/codemod-syntax.ts.txt +3 -0
  225. package/src/cli/__tests__/fixtures/migrate-operation-declaration/connection-precedence.ts.txt +10 -0
  226. package/src/cli/__tests__/fixtures/migrate-operation-declaration/docs-conflict.ts.txt +8 -0
  227. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-hoisted-array-spread.ts.txt +15 -0
  228. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-imported-array-spread.ts.txt +9 -0
  229. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-map.ts.txt +5 -0
  230. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-mixed-array-spread.ts.txt +24 -0
  231. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-operation.ts.txt +16 -0
  232. package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-map.ts.txt +3 -0
  233. package/src/cli/__tests__/fixtures/migrate-operation-declaration/hoist-all.ts.txt +31 -0
  234. package/src/cli/__tests__/fixtures/migrate-operation-declaration/hoisted-const.ts.txt +11 -0
  235. package/src/cli/__tests__/fixtures/migrate-operation-declaration/imported-spread.ts.txt +11 -0
  236. package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-map.ts.txt +11 -0
  237. package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-cast-tail.ts.txt +21 -0
  238. package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-ekitan.ts.txt +11 -0
  239. package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-override.ts.txt +14 -0
  240. package/src/cli/__tests__/fixtures/migrate-operation-declaration/missing-english-locale.ts.txt +7 -0
  241. package/src/cli/__tests__/fixtures/migrate-operation-declaration/no-safety.ts.txt +6 -0
  242. package/src/cli/__tests__/fixtures/migrate-operation-declaration/non-literal.ts.txt +7 -0
  243. package/src/cli/__tests__/fixtures/migrate-operation-declaration/redundant-approval.ts.txt +6 -0
  244. package/src/cli/__tests__/fixtures/migrate-operation-declaration/safety-conflict.ts.txt +7 -0
  245. package/src/cli/__tests__/fixtures/migrate-operation-declaration/stream.ts.txt +7 -0
  246. package/src/cli/__tests__/fixtures/migrate-operation-declaration/tool-router-spread.ts.txt +15 -0
  247. package/src/cli/__tests__/fixtures/migrate-operation-declaration/unparseable.ts.txt +4 -0
  248. package/src/cli/__tests__/fixtures/migrate-operation-declaration/verbatim-template.ts.txt +12 -0
  249. package/src/cli/commands.ts +33 -0
  250. package/src/cli/create.ts +50 -37
  251. package/src/cli/migrate-operation-declaration.ts +1751 -0
  252. package/src/cli/migrate-operation-shape.ts +184 -0
  253. package/src/cli/migrate-provider-shape.ts +772 -0
  254. package/src/cli/prompt-assets.ts +865 -0
  255. package/src/cli/templates/provider/AGENTS.md.tpl +17 -8
  256. package/src/cli/templates/provider/Dockerfile.tpl +1 -1
  257. package/src/cli/templates/provider/README.md.tpl +5 -5
  258. package/src/cli/templates/provider/index.ts.tpl +6 -3
  259. package/src/cli/templates/provider/operations/ping.ts.tpl +4 -1
  260. package/src/cli/templates/provider/provider.json.tpl +6 -0
  261. package/src/config/loader.ts +690 -163
  262. package/src/contract-serialization.ts +5 -7
  263. package/src/contract-types.ts +12 -5
  264. package/src/contract.ts +24 -10
  265. package/src/declaration-validation.ts +330 -0
  266. package/src/define.ts +1048 -131
  267. package/src/dev.ts +4 -1
  268. package/src/engine.ts +279 -0
  269. package/src/error-observability.ts +64 -0
  270. package/src/error-resolution.ts +127 -0
  271. package/src/errors.ts +68 -0
  272. package/src/fixture-sanitization.ts +264 -0
  273. package/src/health-scenario.ts +875 -0
  274. package/src/index.ts +220 -13
  275. package/src/lint.ts +698 -90
  276. package/src/native-address.ts +340 -0
  277. package/src/native-egress-policy.ts +358 -0
  278. package/src/observability.ts +51 -1
  279. package/src/provider.ts +161 -3
  280. package/src/runtime/auth-flow.ts +12 -0
  281. package/src/runtime/browser.ts +661 -63
  282. package/src/runtime/cache.ts +189 -14
  283. package/src/runtime/choice-wordlist.ts +145 -0
  284. package/src/runtime/choice.ts +631 -120
  285. package/src/runtime/chrome149-header-order.ts +330 -0
  286. package/src/runtime/env.ts +13 -0
  287. package/src/runtime/executor.ts +43 -31
  288. package/src/runtime/http.ts +641 -61
  289. package/src/runtime/insights.ts +2 -2
  290. package/src/runtime/instrumentation.ts +520 -15
  291. package/src/runtime/native-network-errors.ts +99 -0
  292. package/src/runtime/native-network.ts +1605 -0
  293. package/src/runtime/ocr.ts +523 -0
  294. package/src/runtime/otlp.ts +467 -21
  295. package/src/runtime/proxy-errors.ts +12 -4
  296. package/src/runtime/proxy-nodemaven.ts +221 -0
  297. package/src/runtime/proxy-telemetry.ts +244 -75
  298. package/src/runtime/redirects.ts +66 -0
  299. package/src/runtime/redis.ts +7 -2
  300. package/src/runtime/request-options.ts +680 -1
  301. package/src/runtime/resolver-config.ts +6 -0
  302. package/src/runtime/resolver-public.ts +23 -0
  303. package/src/runtime/resolver-shared.ts +33 -0
  304. package/src/runtime/resolver-vendors/bindings.ts +56 -0
  305. package/src/runtime/resolver-vendors/browser.ts +533 -0
  306. package/src/runtime/resolver-vendors/capsolver.ts +707 -0
  307. package/src/runtime/resolver-vendors/hosts.ts +38 -0
  308. package/src/runtime/resolver-vendors/twocaptcha.ts +540 -0
  309. package/src/runtime/resolver-vendors/types.ts +212 -0
  310. package/src/runtime/resolver.ts +1157 -0
  311. package/src/runtime/secrets.ts +64 -0
  312. package/src/runtime/state.ts +394 -77
  313. package/src/runtime/stealth-cookies.ts +132 -0
  314. package/src/runtime/stealth.ts +1280 -336
  315. package/src/runtime/stt.ts +1 -19
  316. package/src/runtime/timeout.ts +18 -0
  317. package/src/runtime/trace-config.ts +78 -0
  318. package/src/runtime/trace.ts +57 -17
  319. package/src/serve.ts +6 -1
  320. package/src/server/error-observability.ts +1 -0
  321. package/src/server/index.ts +34 -2
  322. package/src/server/self-test-input-tokens.ts +29 -14
  323. package/src/server/self-test.ts +191 -68
  324. package/src/server/serve-implementation.ts +3378 -0
  325. package/src/server/serve.ts +1 -1632
  326. package/src/server/trace-output.ts +129 -0
  327. package/src/server/types.ts +13 -1
  328. package/src/stateful/README.md +146 -0
  329. package/src/stateful/errors.ts +35 -0
  330. package/src/stateful/http-provider-event-emitter.ts +314 -0
  331. package/src/stateful/http-session-owner-registry.ts +306 -0
  332. package/src/stateful/index.ts +18 -0
  333. package/src/stateful/provider-event-delivery-failures.ts +80 -0
  334. package/src/stateful/provider-event-pipeline-metrics.ts +95 -0
  335. package/src/stateful/provider-event-pipeline.ts +61 -0
  336. package/src/stateful/provider-events.ts +462 -0
  337. package/src/stateful/session-key.ts +111 -0
  338. package/src/stateful/stateful-provider-adapter-context.ts +59 -0
  339. package/src/stateful/stateful-provider-adapter-metrics.ts +48 -0
  340. package/src/stateful/stateful-provider-adapter.ts +562 -0
  341. package/src/stateful/stateful-provider-observability.ts +261 -0
  342. package/src/stateful/stateful-provider-owner-forwarder.ts +287 -0
  343. package/src/stateful/stateful-provider-runtime-context.ts +92 -0
  344. package/src/stateful/stateful-provider-runtime-executor.ts +96 -0
  345. package/src/stateful/stateful-provider-session-routing.ts +546 -0
  346. package/src/stateful/stateful-provider-session-runtime.ts +403 -0
  347. package/src/stateful-signing.ts +46 -0
  348. package/src/stealth/profiles.ts +202 -231
  349. package/src/stream-evidence.ts +988 -0
  350. package/src/stream.ts +8 -1
  351. package/src/testing/index.ts +10 -1
  352. package/src/testing/run.ts +658 -15
  353. package/src/trace-sanitization.ts +63 -0
  354. package/src/types.ts +788 -174
  355. package/dist/cli/templates/provider/CLAUDE.md.tpl +0 -1
  356. package/src/cli/templates/provider/CLAUDE.md.tpl +0 -1
  357. /package/dist/cli/templates/provider/{skills → .agents/skills}/fixtures-and-recording/SKILL.md.tpl +0 -0
  358. /package/dist/cli/templates/provider/{skills → .agents/skills}/health-checks-and-fail-closed/SKILL.md.tpl +0 -0
  359. /package/dist/cli/templates/provider/{skills → .agents/skills}/normalization-standards/SKILL.md.tpl +0 -0
  360. /package/dist/cli/templates/provider/{skills → .agents/skills}/pagination-and-counts/SKILL.md.tpl +0 -0
  361. /package/dist/cli/templates/provider/{skills → .agents/skills}/upstream-contract-verification/SKILL.md.tpl +0 -0
  362. /package/dist/cli/templates/provider/{skills → .agents/skills}/upstream-notes/README.md.tpl +0 -0
  363. /package/src/cli/templates/provider/{skills → .agents/skills}/fixtures-and-recording/SKILL.md.tpl +0 -0
  364. /package/src/cli/templates/provider/{skills → .agents/skills}/health-checks-and-fail-closed/SKILL.md.tpl +0 -0
  365. /package/src/cli/templates/provider/{skills → .agents/skills}/normalization-standards/SKILL.md.tpl +0 -0
  366. /package/src/cli/templates/provider/{skills → .agents/skills}/pagination-and-counts/SKILL.md.tpl +0 -0
  367. /package/src/cli/templates/provider/{skills → .agents/skills}/upstream-contract-verification/SKILL.md.tpl +0 -0
  368. /package/src/cli/templates/provider/{skills → .agents/skills}/upstream-notes/README.md.tpl +0 -0
@@ -1,1131 +1 @@
1
- import { existsSync } from "node:fs";
2
- import { join } from "node:path";
3
- import { Hono } from "hono";
4
- import { z } from "zod";
5
- import { AuthAbortError, createAuthFlowHelpers } from "../auth.js";
6
- import { AuthError, isProviderError, isSessionExpiredError, isTransportError, ProviderError, } from "../errors.js";
7
- import { loadProviderLocaleCatalogs, localizeAuthTurn, } from "../i18n/catalog.js";
8
- import { categoryForStatus, isRetryableCategory, PROVIDER_OBSERVABILITY_TAXONOMY_VERSION, } from "../observability.js";
9
- import { createScratchpad } from "../runtime/auth-flow.js";
10
- import { createBrowserClient } from "../runtime/browser.js";
11
- import { createProviderCache } from "../runtime/cache.js";
12
- import { createProviderChoiceContext, PROVIDER_RUNTIME_CHOICE_TOKEN_MASTER_SECRET_ENV, } from "../runtime/choice.js";
13
- import { createCredentialContext } from "../runtime/credential.js";
14
- import { createEnvContext } from "../runtime/env.js";
15
- import { executeOperation } from "../runtime/executor.js";
16
- import { createHttpClient } from "../runtime/http.js";
17
- import { wrapWithInstrumentation } from "../runtime/instrumentation.js";
18
- import { getProviderBaseUrl } from "../runtime/provider.js";
19
- import { PROXY_AUTH_IP_DENIED_CODE, PROXY_EDGE_AUTH_REJECTED_CODE, PROXY_POOL_EXHAUSTED_CODE, } from "../runtime/proxy-errors.js";
20
- import { PROVIDER_TELEMETRY_HEADER, ProxyTelemetryCollector } from "../runtime/proxy-telemetry.js";
21
- import { createProviderRuntimeStateFromEnv, createUnsupportedProviderRuntimeState, } from "../runtime/state.js";
22
- import { createStealthClient } from "../runtime/stealth.js";
23
- import { createSttClientFromEnv } from "../runtime/stt.js";
24
- import { createTraceContext } from "../runtime/trace.js";
25
- import { parseSchema } from "../schema.js";
26
- import { getStealthProfile } from "../stealth/profiles.js";
27
- import { APIFUSE_STREAM_DONE_EVENT, APIFUSE_STREAM_ERROR_EVENT, encodeSseEvent, error as streamError, } from "../stream.js";
28
- import { createSelfTestApp, createSelfTestAuthFlowInvoke, createSelfTestInvoke, resolveSelfTestPort, } from "./self-test.js";
29
- import { resolveSelfTestMasterSecrets } from "./self-test-token.js";
30
- import { AuthFlowRequestSchema, OperationRequestSchema, } from "./types.js";
31
- const DEFAULT_HOST = "0.0.0.0";
32
- const DEFAULT_PORT = 3000;
33
- const AUTH_FLOW_LOCALES = ["en", "ko", "ja"];
34
- const retryResponseMeta = new WeakMap();
35
- function createAuthStub() {
36
- return {
37
- async requestField(name) {
38
- throw new ProviderError(`Auth prompt is unavailable for ${name}`, {
39
- code: "AUTH_PROMPT_UNAVAILABLE",
40
- });
41
- },
42
- };
43
- }
44
- function createBrowserStub() {
45
- return {
46
- engine: "playwright-stealth",
47
- async close() { },
48
- async newPage() {
49
- throw new ProviderError("Browser runtime is not available", {
50
- code: "BROWSER_RUNTIME_UNSUPPORTED",
51
- });
52
- },
53
- async rawPage() {
54
- throw new ProviderError("Browser runtime is not available", {
55
- code: "BROWSER_RUNTIME_UNSUPPORTED",
56
- });
57
- },
58
- async withIsolatedContext() {
59
- throw new ProviderError("Browser runtime is not available", {
60
- code: "BROWSER_RUNTIME_UNSUPPORTED",
61
- });
62
- },
63
- async solveChallenge() {
64
- throw new ProviderError("Browser runtime is not available", {
65
- code: "BROWSER_RUNTIME_UNSUPPORTED",
66
- });
67
- },
68
- };
69
- }
70
- function createStealthStub() {
71
- return {
72
- async fetch() {
73
- throw new ProviderError("Stealth runtime is not available", {
74
- code: "STEALTH_RUNTIME_UNSUPPORTED",
75
- });
76
- },
77
- createSession() {
78
- throw new ProviderError("Stealth runtime is not available", {
79
- code: "STEALTH_RUNTIME_UNSUPPORTED",
80
- });
81
- },
82
- close() {
83
- // no-op
84
- },
85
- };
86
- }
87
- function getProviderStealthBaseUrl(provider) {
88
- const baseUrl = getProviderBaseUrl(provider);
89
- if (baseUrl) {
90
- return baseUrl;
91
- }
92
- const firstHost = provider.allowedHosts?.[0];
93
- return firstHost ? `https://${firstHost}` : undefined;
94
- }
95
- function getProviderStealthProfile(provider) {
96
- return provider.stealth?.profile ? getStealthProfile(provider.stealth.profile) : undefined;
97
- }
98
- function isProductionProviderBrowserMode(provider, env = process.env) {
99
- if (provider.runtime !== "browser") {
100
- return false;
101
- }
102
- if (env.APIFUSE__PROVIDER__RUNTIME === "browser") {
103
- return true;
104
- }
105
- return env.NODE_ENV === "production" && env.APIFUSE__PROVIDER__ID === provider.id;
106
- }
107
- export function resolveProviderProxyAffinityKey(provider, request, operationId) {
108
- const connectionKey = resolveOperationConnectionId(request) ?? request.connection?.externalRef;
109
- const affinity = typeof provider.proxy === "object" ? provider.proxy.session?.affinity : undefined;
110
- if (affinity === "operation") {
111
- return `${provider.id}/${operationId}`;
112
- }
113
- return connectionKey ?? provider.id;
114
- }
115
- function resolveOperationConnectionId(request) {
116
- return request.connection?.id ?? request.connectionId;
117
- }
118
- function createProviderContext(provider, request, operationId, options = {}, state = createUnsupportedProviderRuntimeState(), proxyTelemetry) {
119
- const baseUrl = getProviderBaseUrl(provider);
120
- const stealthBaseUrl = getProviderStealthBaseUrl(provider);
121
- const stealthProfile = getProviderStealthProfile(provider);
122
- const proxyClientOptions = {
123
- upstream: { proxy: provider.proxy },
124
- affinityKey: resolveProviderProxyAffinityKey(provider, request, operationId),
125
- telemetry: proxyTelemetry,
126
- };
127
- let wrappedContext;
128
- const stealthClientOptions = {
129
- upstream: proxyClientOptions.upstream,
130
- affinityKey: proxyClientOptions.affinityKey,
131
- telemetry: proxyTelemetry,
132
- };
133
- const env = createEnvContext([
134
- ...(provider.secrets?.map((secret) => secret.name) ?? []),
135
- PROVIDER_RUNTIME_CHOICE_TOKEN_MASTER_SECRET_ENV,
136
- ]);
137
- const credential = createCredentialContext({
138
- allowedKeys: provider.credential?.keys,
139
- mode: request.connection?.mode,
140
- scopes: request.connection?.scopes,
141
- values: request.connection?.secrets,
142
- });
143
- const requestContext = {
144
- connectionId: resolveOperationConnectionId(request),
145
- headers: request.headers ?? {},
146
- };
147
- const context = wrapWithInstrumentation({
148
- env,
149
- credential,
150
- request: requestContext,
151
- http: createHttpClient(baseUrl, {
152
- ...proxyClientOptions,
153
- onRetrySummary: (summary) => {
154
- if (summary.attempts <= 1 || !wrappedContext)
155
- return;
156
- retryResponseMeta.set(wrappedContext, summary);
157
- },
158
- }),
159
- cache: createProviderCache({ providerId: provider.id }),
160
- state,
161
- stealth: stealthBaseUrl
162
- ? stealthProfile
163
- ? createStealthClient(stealthBaseUrl, stealthProfile.name, stealthClientOptions)
164
- : createStealthClient(stealthBaseUrl, stealthClientOptions)
165
- : createStealthStub(),
166
- browser: provider.runtime === "browser"
167
- ? createBrowserClient({
168
- allowedHosts: provider.allowedHosts,
169
- cdpUrl: process.env.APIFUSE__CDP_POOL__URL,
170
- headless: true,
171
- requireCdpPool: isProductionProviderBrowserMode(provider),
172
- stealth: true,
173
- engine: provider.browser?.engine,
174
- })
175
- : createBrowserStub(),
176
- trace: createTraceContext(),
177
- auth: createAuthStub(),
178
- stt: options.stt ?? createSttClientFromEnv(provider.stt),
179
- choice: createProviderChoiceContext({
180
- providerId: provider.id,
181
- env,
182
- request: requestContext,
183
- credential,
184
- state,
185
- }),
186
- });
187
- wrappedContext = context;
188
- return context;
189
- }
190
- function createFlowContextStore(allowedKeys, initialContext = {}) {
191
- const context = createScratchpad(allowedKeys, initialContext);
192
- return {
193
- context,
194
- getPatch() {
195
- const next = context.toJSON();
196
- const patch = new Map();
197
- for (const [key, value] of Object.entries(next)) {
198
- if (initialContext[key] !== value) {
199
- patch.set(key, value);
200
- }
201
- }
202
- for (const key of Object.keys(initialContext)) {
203
- if (!(key in next)) {
204
- patch.set(key, null);
205
- }
206
- }
207
- if (patch.size === 0) {
208
- return undefined;
209
- }
210
- return Object.fromEntries(patch.entries());
211
- },
212
- };
213
- }
214
- function createAuthFlowContext(provider, request, options = {}, signal) {
215
- const baseUrl = getProviderBaseUrl(provider);
216
- const stealthBaseUrl = getProviderStealthBaseUrl(provider);
217
- const stealthProfile = getProviderStealthProfile(provider);
218
- const contextData = request.context ?? {};
219
- const flowContextStore = createFlowContextStore(provider.context?.keys ?? Object.keys(contextData), contextData);
220
- const proxyClientOptions = {
221
- upstream: { proxy: provider.proxy },
222
- affinityKey: request.connectionId ??
223
- request.externalRef ??
224
- request.tenantId ??
225
- request.providerId ??
226
- provider.id,
227
- };
228
- const stealthClientOptions = {
229
- upstream: proxyClientOptions.upstream,
230
- affinityKey: proxyClientOptions.affinityKey,
231
- };
232
- const credential = request.connection
233
- ? createCredentialContext({
234
- allowedKeys: provider.credential?.keys,
235
- mode: request.connection.mode,
236
- scopes: request.connection.scopes,
237
- values: request.connection.secrets,
238
- })
239
- : undefined;
240
- return {
241
- context: {
242
- connectionId: request.connectionId,
243
- externalRef: request.externalRef,
244
- tenantId: request.tenantId ?? "",
245
- providerId: request.providerId ?? provider.id,
246
- http: createHttpClient(baseUrl, proxyClientOptions),
247
- stealth: stealthBaseUrl
248
- ? stealthProfile
249
- ? createStealthClient(stealthBaseUrl, stealthProfile.name, stealthClientOptions)
250
- : createStealthClient(stealthBaseUrl, stealthClientOptions)
251
- : createStealthStub(),
252
- env: createEnvContext(provider.secrets?.map((secret) => secret.name)),
253
- credential,
254
- context: flowContextStore.context,
255
- stt: options.stt ?? createSttClientFromEnv(provider.stt),
256
- auth: createAuthFlowHelpers({ signal }),
257
- },
258
- getPatch: flowContextStore.getPatch,
259
- };
260
- }
261
- const defaultProviderServerLogger = (event) => {
262
- const line = JSON.stringify(event);
263
- if (event.level === "info") {
264
- console.log(line);
265
- return;
266
- }
267
- console.error(line);
268
- };
269
- function startRequestCost() {
270
- return {
271
- startedAtMs: performance.now(),
272
- cpuStart: process.cpuUsage(),
273
- };
274
- }
275
- function finishRequestCost(input) {
276
- const cpuDelta = process.cpuUsage(input.cpuStart);
277
- return {
278
- durationMs: Math.max(0, Math.round(performance.now() - input.startedAtMs)),
279
- cpuUserMicros: Math.max(0, cpuDelta.user),
280
- cpuSystemMicros: Math.max(0, cpuDelta.system),
281
- cpuTotalMicros: Math.max(0, cpuDelta.user + cpuDelta.system),
282
- };
283
- }
284
- function zodDetails(error) {
285
- return error.issues.map((issue) => ({
286
- path: issue.path.join("."),
287
- code: issue.code,
288
- message: issue.message,
289
- }));
290
- }
291
- function toErrorResponse(error, requestId) {
292
- if (isProviderError(error)) {
293
- const details = publicProviderErrorDetails(error);
294
- return {
295
- error: {
296
- code: error.code ?? "provider_error",
297
- message: publicProviderErrorMessage(error),
298
- ...(requestId ? { requestId } : {}),
299
- ...(error.fix ? { fix: error.fix } : {}),
300
- ...(details ? { details } : {}),
301
- },
302
- };
303
- }
304
- if (error instanceof z.ZodError) {
305
- return {
306
- error: {
307
- code: "invalid_request",
308
- message: "Invalid request body",
309
- ...(requestId ? { requestId } : {}),
310
- details: zodDetails(error),
311
- },
312
- };
313
- }
314
- return {
315
- error: {
316
- code: "internal_error",
317
- message: "Internal error",
318
- ...(requestId ? { requestId } : {}),
319
- },
320
- };
321
- }
322
- function publicProviderErrorDetails(error) {
323
- const providerDetails = error.details;
324
- const observabilityDetails = providerObservabilityDetails(error);
325
- if (providerDetails === undefined) {
326
- return observabilityDetails;
327
- }
328
- if (observabilityDetails === undefined) {
329
- return providerDetails;
330
- }
331
- if (isPlainRecord(providerDetails) && isPlainRecord(observabilityDetails)) {
332
- return { ...providerDetails, ...observabilityDetails };
333
- }
334
- return {
335
- provider: providerDetails,
336
- observability: observabilityDetails,
337
- };
338
- }
339
- function isPlainRecord(value) {
340
- return value !== null && typeof value === "object" && !Array.isArray(value);
341
- }
342
- // Accepts `unknown` so the branded guards narrow cleanly from the top: the
343
- // subtype error classes are structurally compatible with ProviderError, so
344
- // narrowing from a ProviderError-typed value would collapse the negative branch
345
- // to `never`. Narrowing from unknown avoids that while still recognizing errors
346
- // from a duplicate SDK module instance.
347
- function providerObservabilityDetails(error) {
348
- // Session-expiry surfaces the credential_expired category + the opt-in
349
- // retryable signal so Gateway/Credential Service can refresh and re-drive the
350
- // operation (see design.md §4.3 D3). Without this branch the auth error would
351
- // serialize as a bare 401 with no retryable/category, losing the refresh
352
- // signal for exactly the retryOnAuthRefresh operations it is meant to enable.
353
- if (isSessionExpiredError(error)) {
354
- return {
355
- category: error.options?.category ?? "credential_expired",
356
- taxonomyVersion: PROVIDER_OBSERVABILITY_TAXONOMY_VERSION,
357
- retryable: error.options?.retryable ?? false,
358
- };
359
- }
360
- if (!isTransportError(error)) {
361
- return undefined;
362
- }
363
- const isProxyPoolCode = error.code === PROXY_POOL_EXHAUSTED_CODE ||
364
- error.code === PROXY_EDGE_AUTH_REJECTED_CODE ||
365
- error.code === "PROXY_ALLOCATION_FAILED";
366
- const category = error.options?.category ??
367
- (isProxyPoolCode
368
- ? "proxy_pool"
369
- : error.code === PROXY_AUTH_IP_DENIED_CODE
370
- ? "anti_bot_blocked"
371
- : error.code === "transport_timeout"
372
- ? "timeout"
373
- : error.code === "transport_network_error"
374
- ? "network"
375
- : error.upstreamStatus
376
- ? categoryForStatus(error.upstreamStatus)
377
- : "upstream_http");
378
- return {
379
- category,
380
- taxonomyVersion: PROVIDER_OBSERVABILITY_TAXONOMY_VERSION,
381
- retryable: error.options?.retryable ??
382
- (category === "upstream_http" && error.upstreamStatus
383
- ? error.upstreamStatus >= 500
384
- : isRetryableCategory(category)),
385
- ...(error.upstreamStatus ? { upstreamStatus: error.upstreamStatus } : {}),
386
- };
387
- }
388
- function publicProviderErrorMessage(error) {
389
- if (isTransportError(error)) {
390
- if (error.code === PROXY_AUTH_IP_DENIED_CODE) {
391
- return error.message;
392
- }
393
- if (error.code === PROXY_EDGE_AUTH_REJECTED_CODE) {
394
- return error.message;
395
- }
396
- if (error.code === PROXY_POOL_EXHAUSTED_CODE) {
397
- return error.message;
398
- }
399
- if (error.code === "transport_timeout")
400
- return "Request timed out";
401
- if (error.code === "transport_network_error")
402
- return "Network error";
403
- if (error.code === "upstream_http_error" && error.status) {
404
- return `Upstream request failed with status ${error.status}`;
405
- }
406
- if (error.status) {
407
- return `Upstream request failed with status ${error.status}`;
408
- }
409
- return "Upstream request failed";
410
- }
411
- return error.message;
412
- }
413
- function toStatusCode(error) {
414
- if (error instanceof z.ZodError) {
415
- return 400;
416
- }
417
- if (isTransportError(error)) {
418
- return error.code === "transport_timeout" ? 504 : 502;
419
- }
420
- if (isProviderError(error)) {
421
- switch (error.code) {
422
- case "AUTH_REQUIRED":
423
- case "reauth_required":
424
- return 401;
425
- case "NOT_FOUND":
426
- case "not_found":
427
- case "NO_DATA":
428
- return 404;
429
- case "RATE_LIMITED":
430
- case "UPSTREAM_RATE_LIMIT":
431
- case "LIMITED_NUMBER_OF_SERVICE_REQUESTS_EXCEEDS_ERROR":
432
- return 429;
433
- case "UPSTREAM_ERROR":
434
- case "BLOCKED":
435
- return 502;
436
- case "STT_UNAVAILABLE":
437
- case "UNSUPPORTED_STT_BACKEND":
438
- return 503;
439
- }
440
- return 400;
441
- }
442
- return 500;
443
- }
444
- function extractRequestId(raw) {
445
- if (!raw || typeof raw !== "object") {
446
- return undefined;
447
- }
448
- const value = Object.getOwnPropertyDescriptor(raw, "requestId")?.value;
449
- return typeof value === "string" ? value : undefined;
450
- }
451
- function logProviderError(logger, provider, kind, route, requestId, error, status, cost) {
452
- const code = isProviderError(error)
453
- ? (error.code ?? "provider_error")
454
- : error instanceof z.ZodError
455
- ? "invalid_request"
456
- : "internal_error";
457
- const errorClass = error instanceof Error ? error.name : typeof error;
458
- const message = error instanceof Error ? error.message : String(error);
459
- const details = isProviderError(error) ? providerObservabilityDetails(error) : undefined;
460
- const emit = typeof logger === "function" ? logger : defaultProviderServerLogger;
461
- emit({
462
- level: status >= 500 ? "error" : "warn",
463
- event: "provider_request_failed",
464
- providerId: provider.id,
465
- kind,
466
- route,
467
- ...(requestId ? { requestId } : {}),
468
- status,
469
- ...cost,
470
- code,
471
- errorClass,
472
- message,
473
- ...(isTransportError(error) && error.upstreamStatus
474
- ? { upstreamStatus: error.upstreamStatus }
475
- : {}),
476
- ...(details
477
- ? {
478
- errorCategory: details.category,
479
- taxonomyVersion: details.taxonomyVersion,
480
- retryable: details.retryable,
481
- }
482
- : {}),
483
- ...(error instanceof z.ZodError ? { issues: zodDetails(error) } : {}),
484
- });
485
- }
486
- function logProviderCleanupError(logger, provider, operationId, requestId, resource, error) {
487
- const emit = typeof logger === "function" ? logger : defaultProviderServerLogger;
488
- const errorClass = error instanceof Error ? error.name : typeof error;
489
- const message = error instanceof Error ? error.message : String(error);
490
- emit({
491
- level: "warn",
492
- event: "provider_cleanup_failed",
493
- providerId: provider.id,
494
- kind: "operation",
495
- route: operationId,
496
- ...(requestId ? { requestId } : {}),
497
- resource,
498
- errorClass,
499
- message,
500
- });
501
- }
502
- function logProviderSuccess(logger, provider, kind, route, requestId, status, cost) {
503
- const emit = typeof logger === "function" ? logger : defaultProviderServerLogger;
504
- emit({
505
- level: "info",
506
- event: "provider_request_completed",
507
- providerId: provider.id,
508
- kind,
509
- route,
510
- ...(requestId ? { requestId } : {}),
511
- status,
512
- ...cost,
513
- });
514
- }
515
- function toJsonSuccessResponse(result, ctx) {
516
- if (result instanceof Response) {
517
- return result;
518
- }
519
- if (result instanceof ReadableStream) {
520
- return new Response(result);
521
- }
522
- const cacheMeta = ctx?.cache.responseMeta();
523
- const retryMeta = ctx ? retryResponseMeta.get(ctx) : undefined;
524
- const meta = cacheMeta || retryMeta
525
- ? {
526
- ...(cacheMeta
527
- ? {
528
- cached: cacheMeta.hit,
529
- stale: cacheMeta.stale,
530
- cache: cacheMeta,
531
- }
532
- : {}),
533
- ...(retryMeta ? { retry: retryMeta } : {}),
534
- }
535
- : undefined;
536
- return {
537
- data: result,
538
- ...(meta ? { meta } : {}),
539
- };
540
- }
541
- function isAsyncIterable(value) {
542
- if (!value || typeof value !== "object")
543
- return false;
544
- const iterator = Reflect.get(value, Symbol.asyncIterator);
545
- return typeof iterator === "function";
546
- }
547
- function responseWithCleanup(response, cleanup) {
548
- if (!response.body) {
549
- void cleanup();
550
- return response;
551
- }
552
- const reader = response.body.getReader();
553
- let cleaned = false;
554
- const runCleanup = async () => {
555
- if (cleaned)
556
- return;
557
- cleaned = true;
558
- await cleanup();
559
- };
560
- const body = new ReadableStream({
561
- async pull(controller) {
562
- try {
563
- const { done, value } = await reader.read();
564
- if (done) {
565
- controller.close();
566
- await runCleanup();
567
- return;
568
- }
569
- if (value)
570
- controller.enqueue(value);
571
- }
572
- catch (error) {
573
- await runCleanup();
574
- controller.error(error);
575
- }
576
- },
577
- async cancel(reason) {
578
- try {
579
- await reader.cancel(reason);
580
- }
581
- finally {
582
- await runCleanup();
583
- }
584
- },
585
- });
586
- return new Response(body, {
587
- headers: response.headers,
588
- status: response.status,
589
- statusText: response.statusText,
590
- });
591
- }
592
- async function validateSseEvent(operation, event) {
593
- const transport = getSseTransport(operation);
594
- const schema = transport?.events?.[event.event];
595
- if (!schema) {
596
- if (event.event === APIFUSE_STREAM_ERROR_EVENT || event.event === APIFUSE_STREAM_DONE_EVENT) {
597
- return event;
598
- }
599
- throw new ProviderError(`SSE event "${event.event}" is not declared in operation transport.events.`, {
600
- code: "SSE_EVENT_UNDECLARED",
601
- category: "output_validation",
602
- retryable: false,
603
- fix: `Add "${event.event}" to transport.events or stop emitting that event.`,
604
- });
605
- }
606
- const data = await parseSchema(schema, event.data, `transport.events.${event.event}`);
607
- return { ...event, data };
608
- }
609
- function byteLength(value) {
610
- if (typeof value === "string") {
611
- return new TextEncoder().encode(value).byteLength;
612
- }
613
- return value.byteLength;
614
- }
615
- function assertStreamPayloadWithinLimit(actualBytes, maxBytes, kind) {
616
- if (maxBytes === undefined || actualBytes <= maxBytes)
617
- return;
618
- throw new ProviderError(`Stream ${kind} exceeded declared byte limit (${actualBytes} > ${maxBytes}).`, {
619
- code: kind === "event" ? "STREAM_EVENT_TOO_LARGE" : "STREAM_CHUNK_TOO_LARGE",
620
- retryable: false,
621
- category: "input_validation",
622
- fix: kind === "event"
623
- ? "Emit smaller SSE events or increase transport.maxEventBytes."
624
- : "Emit smaller stream chunks or increase transport.maxChunkBytes.",
625
- });
626
- }
627
- function toSseResponse(operation, result, cleanup, requestId) {
628
- const encoder = new TextEncoder();
629
- const iterator = result[Symbol.asyncIterator]();
630
- const transport = getSseTransport(operation);
631
- let done = false;
632
- let cleaned = false;
633
- const runCleanup = async () => {
634
- if (cleaned)
635
- return;
636
- cleaned = true;
637
- await cleanup();
638
- };
639
- const body = new ReadableStream({
640
- async pull(controller) {
641
- try {
642
- if (done) {
643
- controller.close();
644
- await runCleanup();
645
- return;
646
- }
647
- const next = await iterator.next();
648
- if (next.done) {
649
- done = true;
650
- controller.close();
651
- await runCleanup();
652
- return;
653
- }
654
- const validated = await validateSseEvent(operation, next.value);
655
- const encodedEvent = encodeSseEvent(validated);
656
- const encodedBytes = encoder.encode(encodedEvent);
657
- assertStreamPayloadWithinLimit(encodedBytes.byteLength, transport?.maxEventBytes, "event");
658
- controller.enqueue(encodedBytes);
659
- }
660
- catch (error) {
661
- const message = error instanceof Error ? error.message : "Stream failed";
662
- controller.enqueue(encoder.encode(encodeSseEvent(streamError("stream_error", message, {
663
- ...(requestId ? { requestId } : {}),
664
- }))));
665
- controller.close();
666
- done = true;
667
- await runCleanup();
668
- }
669
- },
670
- async cancel(reason) {
671
- try {
672
- await iterator.return?.(reason);
673
- }
674
- finally {
675
- await runCleanup();
676
- }
677
- },
678
- });
679
- return new Response(body, {
680
- headers: {
681
- "Cache-Control": "no-cache, no-transform",
682
- Connection: "keep-alive",
683
- "Content-Type": "text/event-stream; charset=utf-8",
684
- },
685
- });
686
- }
687
- function enforceStreamChunkLimit(body, maxChunkBytes) {
688
- if (maxChunkBytes === undefined)
689
- return body;
690
- const reader = body.getReader();
691
- return new ReadableStream({
692
- async pull(controller) {
693
- try {
694
- const { done, value } = await reader.read();
695
- if (done) {
696
- controller.close();
697
- return;
698
- }
699
- if (value) {
700
- assertStreamPayloadWithinLimit(byteLength(value), maxChunkBytes, "chunk");
701
- controller.enqueue(value);
702
- }
703
- }
704
- catch (error) {
705
- controller.error(error);
706
- }
707
- },
708
- cancel(reason) {
709
- return reader.cancel(reason);
710
- },
711
- });
712
- }
713
- function toStreamingResponse(operation, result, cleanup, requestId) {
714
- const transport = operation.transport?.kind ?? "json";
715
- if (transport === "sse" && (result instanceof Response || result instanceof ReadableStream)) {
716
- void cleanup();
717
- throw new ProviderError("SSE operations must return an AsyncIterable of typed stream.event(...) values.", {
718
- code: "SSE_RESULT_UNSUPPORTED",
719
- category: "output_validation",
720
- retryable: false,
721
- fix: "Return an async generator that yields stream.event(name, data) so APIFuse can validate event schemas and enforce event byte limits.",
722
- });
723
- }
724
- if (result instanceof Response) {
725
- const httpTransport = getHttpStreamTransport(operation);
726
- if (httpTransport && result.body && httpTransport?.maxChunkBytes !== undefined) {
727
- return responseWithCleanup(new Response(enforceStreamChunkLimit(result.body, httpTransport.maxChunkBytes), {
728
- headers: result.headers,
729
- status: result.status,
730
- statusText: result.statusText,
731
- }), cleanup);
732
- }
733
- return responseWithCleanup(result, cleanup);
734
- }
735
- if (result instanceof ReadableStream) {
736
- const httpTransport = getHttpStreamTransport(operation);
737
- const stream = httpTransport !== undefined
738
- ? enforceStreamChunkLimit(result, httpTransport.maxChunkBytes)
739
- : result;
740
- return responseWithCleanup(new Response(stream, {
741
- headers: transport === "sse"
742
- ? { "Content-Type": "text/event-stream; charset=utf-8" }
743
- : {
744
- "Content-Type": operation.transport?.kind === "http-stream"
745
- ? (operation.transport.contentType ?? "application/octet-stream")
746
- : "application/octet-stream",
747
- },
748
- }), cleanup);
749
- }
750
- if (transport === "sse" && isAsyncIterable(result)) {
751
- return toSseResponse(operation, result, cleanup, requestId);
752
- }
753
- void cleanup();
754
- throw new ProviderError(`Streaming operation returned unsupported result for transport "${transport}"`, {
755
- code: "STREAM_RESULT_UNSUPPORTED",
756
- fix: "Return an AsyncIterable of stream.event(...) values, a ReadableStream, or a Response from streaming operations.",
757
- });
758
- }
759
- function getSseTransport(operation) {
760
- return operation.transport?.kind === "sse" ? operation.transport : undefined;
761
- }
762
- function getHttpStreamTransport(operation) {
763
- return operation.transport?.kind === "http-stream" ? operation.transport : undefined;
764
- }
765
- function toAuthFlowResponse(result, contextPatch) {
766
- if (result instanceof Response) {
767
- return result;
768
- }
769
- if (result instanceof ReadableStream) {
770
- return new Response(result);
771
- }
772
- return {
773
- data: result,
774
- ...(contextPatch ? { contextPatch } : {}),
775
- };
776
- }
777
- function authFlowLocaleFromHeaders(headers) {
778
- const header = Object.entries(headers ?? {}).find(([key]) => key.toLowerCase() === "accept-language")?.[1];
779
- for (const token of (header ?? "").split(",")) {
780
- const language = token.trim().split(";")[0]?.split("-")[0]?.toLowerCase();
781
- if (isAuthFlowLocale(language)) {
782
- return language;
783
- }
784
- }
785
- return "en";
786
- }
787
- function isAuthFlowLocale(value) {
788
- return value === "en" || value === "ko" || value === "ja";
789
- }
790
- function isAuthTurn(value) {
791
- return !!value && typeof value === "object" && "kind" in value && "turnId" in value;
792
- }
793
- function loadAuthFlowLocaleCatalogs(provider) {
794
- for (const providerDir of [
795
- process.cwd(),
796
- join(process.cwd(), "providers", provider.id),
797
- join(process.cwd(), "providers-staging", provider.id),
798
- ]) {
799
- if (!existsSync(join(providerDir, "locales", "en.json")))
800
- continue;
801
- try {
802
- return loadProviderLocaleCatalogs({
803
- providerDir,
804
- locales: AUTH_FLOW_LOCALES,
805
- });
806
- }
807
- catch {
808
- return undefined;
809
- }
810
- }
811
- return undefined;
812
- }
813
- function materializeAuthFlowTurn(provider, request, turn) {
814
- const catalogs = loadAuthFlowLocaleCatalogs(provider);
815
- if (!catalogs)
816
- return turn;
817
- return localizeAuthTurn(turn, {
818
- catalogs,
819
- locale: authFlowLocaleFromHeaders(request.headers),
820
- });
821
- }
822
- function withAuthRequestHeaders(request, headers) {
823
- return {
824
- ...request,
825
- headers: {
826
- ...(request.headers ?? {}),
827
- ...Object.fromEntries(headers.entries()),
828
- },
829
- };
830
- }
831
- async function handleOperation(provider, request, operationId, options = {}, state = createUnsupportedProviderRuntimeState(), proxyTelemetry) {
832
- const ctx = createProviderContext(provider, request, operationId, options, state, proxyTelemetry);
833
- const operation = provider.operations[operationId];
834
- const streaming = operation?.transport?.kind && operation.transport.kind !== "json";
835
- let cleanupCalled = false;
836
- const cleanup = async () => {
837
- if (cleanupCalled)
838
- return;
839
- cleanupCalled = true;
840
- try {
841
- ctx.stealth.close?.();
842
- }
843
- catch (error) {
844
- logProviderCleanupError(options.logger, provider, operationId, request.requestId, "stealth", error);
845
- }
846
- try {
847
- await ctx.browser.close?.();
848
- }
849
- catch (error) {
850
- logProviderCleanupError(options.logger, provider, operationId, request.requestId, "browser", error);
851
- }
852
- };
853
- try {
854
- const result = await executeOperation(provider, operationId, ctx, request.input);
855
- if (streaming && operation) {
856
- return toStreamingResponse(operation, result, cleanup, request.requestId);
857
- }
858
- return toJsonSuccessResponse(result, ctx);
859
- }
860
- catch (error) {
861
- await cleanup();
862
- throw error;
863
- }
864
- finally {
865
- if (!streaming)
866
- await cleanup();
867
- }
868
- }
869
- function responseWithProviderTelemetry(response, proxyTelemetry) {
870
- const headerValue = proxyTelemetry?.toHeaderValue();
871
- const headers = new Headers(response.headers);
872
- headers.delete(PROVIDER_TELEMETRY_HEADER);
873
- if (headerValue)
874
- headers.set(PROVIDER_TELEMETRY_HEADER, headerValue);
875
- return new Response(response.body, {
876
- headers,
877
- status: response.status,
878
- statusText: response.statusText,
879
- });
880
- }
881
- async function handleAuthFlow(provider, request, route, options = {}, signal) {
882
- const flow = provider.auth?.flow;
883
- if (!flow) {
884
- throw new ProviderError("Auth flow is not configured", {
885
- code: "AUTH_FLOW_NOT_CONFIGURED",
886
- });
887
- }
888
- const { context, getPatch } = createAuthFlowContext(provider, request, options, signal);
889
- try {
890
- const result = route === "start"
891
- ? await flow.start(context)
892
- : route === "continue"
893
- ? await flow.continue(context, request.input ?? {})
894
- : route === "poll"
895
- ? flow.poll
896
- ? await flow.poll(context)
897
- : null
898
- : route === "abort"
899
- ? flow.abort
900
- ? await flow.abort(context)
901
- : null
902
- : flow.refresh
903
- ? await flow.refresh(context, request.input ?? {})
904
- : null;
905
- if (route === "refresh" && !flow.refresh) {
906
- throw new AuthError("Provider auth flow does not support refresh.", {
907
- code: "refresh_not_supported",
908
- });
909
- }
910
- const materializedResult = result &&
911
- !(result instanceof Response) &&
912
- !(result instanceof ReadableStream) &&
913
- isAuthTurn(result)
914
- ? materializeAuthFlowTurn(provider, request, result)
915
- : result;
916
- return toAuthFlowResponse(materializedResult, getPatch());
917
- }
918
- catch (error) {
919
- if (error instanceof AuthAbortError) {
920
- return toAuthFlowResponse(error.turn, getPatch());
921
- }
922
- throw error;
923
- }
924
- finally {
925
- context.stealth.close?.();
926
- }
927
- }
928
- export function createServerApp(provider, options = {}) {
929
- const app = new Hono();
930
- const logger = options.logger ?? defaultProviderServerLogger;
931
- const state = options.state ??
932
- createProviderRuntimeStateFromEnv({
933
- providerId: provider.id,
934
- allowMemoryFallback: options.allowMemoryStateFallback === true,
935
- });
936
- app.notFound((c) => c.json({
937
- error: {
938
- code: "not_found",
939
- message: "Not found",
940
- },
941
- }, 404));
942
- app.get("/health", (c) => c.json({
943
- status: "ok",
944
- provider: provider.id,
945
- version: provider.version,
946
- }));
947
- app.post("/v1/:operation", async (c) => {
948
- let rawBody;
949
- const operation = c.req.param("operation");
950
- const proxyTelemetry = new ProxyTelemetryCollector();
951
- const requestCost = startRequestCost();
952
- try {
953
- rawBody = await c.req.raw
954
- .clone()
955
- .json()
956
- .catch(() => undefined);
957
- const body = OperationRequestSchema.parse(rawBody);
958
- const requestHeaders = Object.fromEntries(c.req.raw.headers.entries());
959
- body.headers = { ...requestHeaders, ...body.headers };
960
- const response = await handleOperation(provider, body, operation, options, state, proxyTelemetry);
961
- if (response instanceof Response) {
962
- logProviderSuccess(logger, provider, "operation", operation, body.requestId, response.status, finishRequestCost(requestCost));
963
- return responseWithProviderTelemetry(response, proxyTelemetry);
964
- }
965
- const telemetryHeader = proxyTelemetry.toHeaderValue();
966
- if (telemetryHeader)
967
- c.header(PROVIDER_TELEMETRY_HEADER, telemetryHeader);
968
- logProviderSuccess(logger, provider, "operation", operation, body.requestId, 200, finishRequestCost(requestCost));
969
- return c.json(response);
970
- }
971
- catch (error) {
972
- const status = toStatusCode(error);
973
- const requestId = extractRequestId(rawBody);
974
- logProviderError(logger, provider, "operation", operation, requestId, error, status, finishRequestCost(requestCost));
975
- const telemetryHeader = proxyTelemetry.toHeaderValue();
976
- if (telemetryHeader)
977
- c.header(PROVIDER_TELEMETRY_HEADER, telemetryHeader);
978
- return c.json(toErrorResponse(error, requestId), status);
979
- }
980
- });
981
- app.post("/auth/start", async (c) => {
982
- let rawBody;
983
- const requestCost = startRequestCost();
984
- try {
985
- rawBody = await c.req.raw
986
- .clone()
987
- .json()
988
- .catch(() => undefined);
989
- const body = withAuthRequestHeaders(AuthFlowRequestSchema.parse(rawBody), c.req.raw.headers);
990
- const response = await handleAuthFlow(provider, body, "start", options, c.req.raw.signal);
991
- logProviderSuccess(logger, provider, "auth", "start", body.requestId, response instanceof Response ? response.status : 200, finishRequestCost(requestCost));
992
- return response instanceof Response ? response : c.json(response);
993
- }
994
- catch (error) {
995
- const status = toStatusCode(error);
996
- const requestId = extractRequestId(rawBody);
997
- logProviderError(logger, provider, "auth", "start", requestId, error, status, finishRequestCost(requestCost));
998
- return c.json(toErrorResponse(error, requestId), status);
999
- }
1000
- });
1001
- app.post("/auth/continue", async (c) => {
1002
- let rawBody;
1003
- const requestCost = startRequestCost();
1004
- try {
1005
- rawBody = await c.req.raw
1006
- .clone()
1007
- .json()
1008
- .catch(() => undefined);
1009
- const body = withAuthRequestHeaders(AuthFlowRequestSchema.parse(rawBody), c.req.raw.headers);
1010
- const response = await handleAuthFlow(provider, body, "continue", options, c.req.raw.signal);
1011
- logProviderSuccess(logger, provider, "auth", "continue", body.requestId, response instanceof Response ? response.status : 200, finishRequestCost(requestCost));
1012
- return response instanceof Response ? response : c.json(response);
1013
- }
1014
- catch (error) {
1015
- const status = toStatusCode(error);
1016
- const requestId = extractRequestId(rawBody);
1017
- logProviderError(logger, provider, "auth", "continue", requestId, error, status, finishRequestCost(requestCost));
1018
- return c.json(toErrorResponse(error, requestId), status);
1019
- }
1020
- });
1021
- app.post("/auth/poll", async (c) => {
1022
- let rawBody;
1023
- const requestCost = startRequestCost();
1024
- try {
1025
- rawBody = await c.req.raw
1026
- .clone()
1027
- .json()
1028
- .catch(() => undefined);
1029
- const body = withAuthRequestHeaders(AuthFlowRequestSchema.parse(rawBody), c.req.raw.headers);
1030
- const response = await handleAuthFlow(provider, body, "poll", options, c.req.raw.signal);
1031
- logProviderSuccess(logger, provider, "auth", "poll", body.requestId, response instanceof Response ? response.status : 200, finishRequestCost(requestCost));
1032
- return response instanceof Response ? response : c.json(response);
1033
- }
1034
- catch (error) {
1035
- const status = toStatusCode(error);
1036
- const requestId = extractRequestId(rawBody);
1037
- logProviderError(logger, provider, "auth", "poll", requestId, error, status, finishRequestCost(requestCost));
1038
- return c.json(toErrorResponse(error, requestId), status);
1039
- }
1040
- });
1041
- app.post("/auth/refresh", async (c) => {
1042
- let rawBody;
1043
- const requestCost = startRequestCost();
1044
- try {
1045
- rawBody = await c.req.raw
1046
- .clone()
1047
- .json()
1048
- .catch(() => undefined);
1049
- const body = withAuthRequestHeaders(AuthFlowRequestSchema.parse(rawBody), c.req.raw.headers);
1050
- const response = await handleAuthFlow(provider, body, "refresh", options, c.req.raw.signal);
1051
- logProviderSuccess(logger, provider, "auth", "refresh", body.requestId, response instanceof Response ? response.status : 200, finishRequestCost(requestCost));
1052
- return response instanceof Response ? response : c.json(response);
1053
- }
1054
- catch (error) {
1055
- const status = toStatusCode(error);
1056
- const requestId = extractRequestId(rawBody);
1057
- logProviderError(logger, provider, "auth", "refresh", requestId, error, status, finishRequestCost(requestCost));
1058
- return c.json(toErrorResponse(error, requestId), status);
1059
- }
1060
- });
1061
- app.post("/auth/disconnect", async (c) => {
1062
- let rawBody;
1063
- const requestCost = startRequestCost();
1064
- try {
1065
- rawBody = await c.req.raw
1066
- .clone()
1067
- .json()
1068
- .catch(() => undefined);
1069
- const body = withAuthRequestHeaders(AuthFlowRequestSchema.parse(rawBody), c.req.raw.headers);
1070
- const response = await handleAuthFlow(provider, body, "abort", options, c.req.raw.signal);
1071
- logProviderSuccess(logger, provider, "auth", "disconnect", body.requestId, response instanceof Response ? response.status : 200, finishRequestCost(requestCost));
1072
- return response instanceof Response ? response : c.json(response);
1073
- }
1074
- catch (error) {
1075
- const status = toStatusCode(error);
1076
- const requestId = extractRequestId(rawBody);
1077
- logProviderError(logger, provider, "auth", "disconnect", requestId, error, status, finishRequestCost(requestCost));
1078
- return c.json(toErrorResponse(error, requestId), status);
1079
- }
1080
- });
1081
- return app;
1082
- }
1083
- function getBunServeRuntime() {
1084
- const bunValue = Object.getOwnPropertyDescriptor(globalThis, "Bun")?.value;
1085
- if (!bunValue || typeof bunValue !== "object") {
1086
- return undefined;
1087
- }
1088
- const serve = Object.getOwnPropertyDescriptor(bunValue, "serve")?.value;
1089
- if (typeof serve !== "function") {
1090
- return undefined;
1091
- }
1092
- return {
1093
- serve(options) {
1094
- return serve(options);
1095
- },
1096
- };
1097
- }
1098
- export async function serve(provider, options = {}) {
1099
- const bunRuntime = getBunServeRuntime();
1100
- if (bunRuntime === undefined) {
1101
- throw new ProviderError("Bun runtime is required to start the provider server", {
1102
- code: "RUNTIME_UNSUPPORTED",
1103
- });
1104
- }
1105
- const app = createServerApp(provider, {
1106
- logger: options.logger,
1107
- stt: options.stt,
1108
- });
1109
- bunRuntime.serve({
1110
- port: options.port ?? DEFAULT_PORT,
1111
- hostname: options.host ?? DEFAULT_HOST,
1112
- fetch: app.fetch,
1113
- });
1114
- // Internal self-test listener (health dependency inversion): a SEPARATE
1115
- // socket the tenant-facing gateway never dials. Off by default — it only
1116
- // starts when the shared self-test master secret env is present.
1117
- const selfTestSecrets = resolveSelfTestMasterSecrets();
1118
- if (selfTestSecrets) {
1119
- const selfTestApp = createSelfTestApp(provider, {
1120
- secrets: selfTestSecrets,
1121
- invoke: createSelfTestInvoke(app),
1122
- authFlow: createSelfTestAuthFlowInvoke(app),
1123
- });
1124
- bunRuntime.serve({
1125
- port: options.selfTestPort ?? resolveSelfTestPort(),
1126
- hostname: options.host ?? DEFAULT_HOST,
1127
- fetch: selfTestApp.fetch,
1128
- });
1129
- }
1130
- await Promise.resolve();
1131
- }
1
+ export * from "./serve-implementation.js";