@copilotkit/aimock 1.45.1 → 1.47.0

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 (492) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +25 -1
  4. package/README.md +11 -2
  5. package/dist/agui-mock.cjs +25 -25
  6. package/dist/agui-mock.cjs.map +1 -1
  7. package/dist/agui-mock.d.cts.map +1 -1
  8. package/dist/agui-mock.d.ts.map +1 -1
  9. package/dist/agui-mock.js +25 -25
  10. package/dist/agui-mock.js.map +1 -1
  11. package/dist/agui-types.d.cts.map +1 -1
  12. package/dist/aimock-cli.cjs +15 -1
  13. package/dist/aimock-cli.cjs.map +1 -1
  14. package/dist/aimock-cli.d.cts.map +1 -1
  15. package/dist/aimock-cli.d.ts.map +1 -1
  16. package/dist/aimock-cli.js +16 -2
  17. package/dist/aimock-cli.js.map +1 -1
  18. package/dist/api-key-auth.cjs +10 -9
  19. package/dist/api-key-auth.cjs.map +1 -1
  20. package/dist/api-key-auth.d.cts.map +1 -1
  21. package/dist/api-key-auth.d.ts.map +1 -1
  22. package/dist/api-key-auth.js +11 -10
  23. package/dist/api-key-auth.js.map +1 -1
  24. package/dist/aws-event-stream.cjs +20 -23
  25. package/dist/aws-event-stream.cjs.map +1 -1
  26. package/dist/aws-event-stream.d.cts +0 -1
  27. package/dist/aws-event-stream.d.ts +0 -1
  28. package/dist/aws-event-stream.js +20 -24
  29. package/dist/aws-event-stream.js.map +1 -1
  30. package/dist/batches.cjs +2 -4
  31. package/dist/batches.cjs.map +1 -1
  32. package/dist/batches.d.cts.map +1 -1
  33. package/dist/batches.d.ts.map +1 -1
  34. package/dist/batches.js +2 -4
  35. package/dist/batches.js.map +1 -1
  36. package/dist/bedrock-converse.cjs +139 -161
  37. package/dist/bedrock-converse.cjs.map +1 -1
  38. package/dist/bedrock-converse.d.cts.map +1 -1
  39. package/dist/bedrock-converse.d.ts.map +1 -1
  40. package/dist/bedrock-converse.js +137 -159
  41. package/dist/bedrock-converse.js.map +1 -1
  42. package/dist/bedrock.cjs +175 -216
  43. package/dist/bedrock.cjs.map +1 -1
  44. package/dist/bedrock.d.cts.map +1 -1
  45. package/dist/bedrock.d.ts.map +1 -1
  46. package/dist/bedrock.js +172 -213
  47. package/dist/bedrock.js.map +1 -1
  48. package/dist/byteplus-video.cjs +11 -10
  49. package/dist/byteplus-video.cjs.map +1 -1
  50. package/dist/byteplus-video.d.cts.map +1 -1
  51. package/dist/byteplus-video.d.ts.map +1 -1
  52. package/dist/byteplus-video.js +5 -4
  53. package/dist/byteplus-video.js.map +1 -1
  54. package/dist/chaos.cjs +5 -4
  55. package/dist/chaos.cjs.map +1 -1
  56. package/dist/chaos.d.cts.map +1 -1
  57. package/dist/chaos.d.ts.map +1 -1
  58. package/dist/chaos.js +5 -4
  59. package/dist/chaos.js.map +1 -1
  60. package/dist/cli.cjs +15 -0
  61. package/dist/cli.cjs.map +1 -1
  62. package/dist/cli.js +15 -0
  63. package/dist/cli.js.map +1 -1
  64. package/dist/cohere.cjs +107 -180
  65. package/dist/cohere.cjs.map +1 -1
  66. package/dist/cohere.d.cts.map +1 -1
  67. package/dist/cohere.d.ts.map +1 -1
  68. package/dist/cohere.js +106 -179
  69. package/dist/cohere.js.map +1 -1
  70. package/dist/config-loader.cjs +29 -1
  71. package/dist/config-loader.cjs.map +1 -1
  72. package/dist/config-loader.d.cts +7 -1
  73. package/dist/config-loader.d.cts.map +1 -1
  74. package/dist/config-loader.d.ts +7 -1
  75. package/dist/config-loader.d.ts.map +1 -1
  76. package/dist/config-loader.js +29 -2
  77. package/dist/config-loader.js.map +1 -1
  78. package/dist/count-tokens.cjs +146 -0
  79. package/dist/count-tokens.cjs.map +1 -0
  80. package/dist/count-tokens.js +146 -0
  81. package/dist/count-tokens.js.map +1 -0
  82. package/dist/elevenlabs-audio.cjs +36 -34
  83. package/dist/elevenlabs-audio.cjs.map +1 -1
  84. package/dist/elevenlabs-audio.d.cts.map +1 -1
  85. package/dist/elevenlabs-audio.d.ts.map +1 -1
  86. package/dist/elevenlabs-audio.js +33 -31
  87. package/dist/elevenlabs-audio.js.map +1 -1
  88. package/dist/elevenlabs-voice.cjs +38 -37
  89. package/dist/elevenlabs-voice.cjs.map +1 -1
  90. package/dist/elevenlabs-voice.d.cts.map +1 -1
  91. package/dist/elevenlabs-voice.d.ts.map +1 -1
  92. package/dist/elevenlabs-voice.js +33 -32
  93. package/dist/elevenlabs-voice.js.map +1 -1
  94. package/dist/embedding-request.cjs +16 -0
  95. package/dist/embedding-request.cjs.map +1 -0
  96. package/dist/embedding-request.js +14 -0
  97. package/dist/embedding-request.js.map +1 -0
  98. package/dist/embeddings.cjs +30 -20
  99. package/dist/embeddings.cjs.map +1 -1
  100. package/dist/embeddings.d.cts.map +1 -1
  101. package/dist/embeddings.d.ts.map +1 -1
  102. package/dist/embeddings.js +30 -20
  103. package/dist/embeddings.js.map +1 -1
  104. package/dist/fal-audio.cjs +45 -43
  105. package/dist/fal-audio.cjs.map +1 -1
  106. package/dist/fal-audio.d.cts.map +1 -1
  107. package/dist/fal-audio.d.ts.map +1 -1
  108. package/dist/fal-audio.js +42 -40
  109. package/dist/fal-audio.js.map +1 -1
  110. package/dist/fal.cjs +17 -15
  111. package/dist/fal.cjs.map +1 -1
  112. package/dist/fal.js +16 -14
  113. package/dist/fal.js.map +1 -1
  114. package/dist/files.cjs +2 -4
  115. package/dist/files.cjs.map +1 -1
  116. package/dist/files.d.cts.map +1 -1
  117. package/dist/files.d.ts.map +1 -1
  118. package/dist/files.js +2 -4
  119. package/dist/files.js.map +1 -1
  120. package/dist/fine-tuning.cjs +2 -4
  121. package/dist/fine-tuning.cjs.map +1 -1
  122. package/dist/fine-tuning.d.cts.map +1 -1
  123. package/dist/fine-tuning.d.ts.map +1 -1
  124. package/dist/fine-tuning.js +2 -4
  125. package/dist/fine-tuning.js.map +1 -1
  126. package/dist/fixture-loader.cjs +140 -44
  127. package/dist/fixture-loader.cjs.map +1 -1
  128. package/dist/fixture-loader.d.cts.map +1 -1
  129. package/dist/fixture-loader.d.ts.map +1 -1
  130. package/dist/fixture-loader.js +141 -46
  131. package/dist/fixture-loader.js.map +1 -1
  132. package/dist/gemini-embeddings.cjs +26 -24
  133. package/dist/gemini-embeddings.cjs.map +1 -1
  134. package/dist/gemini-embeddings.js +26 -24
  135. package/dist/gemini-embeddings.js.map +1 -1
  136. package/dist/gemini-interactions.cjs +113 -156
  137. package/dist/gemini-interactions.cjs.map +1 -1
  138. package/dist/gemini-interactions.d.cts +0 -1
  139. package/dist/gemini-interactions.d.cts.map +1 -1
  140. package/dist/gemini-interactions.d.ts +0 -1
  141. package/dist/gemini-interactions.d.ts.map +1 -1
  142. package/dist/gemini-interactions.js +113 -156
  143. package/dist/gemini-interactions.js.map +1 -1
  144. package/dist/gemini.cjs +295 -218
  145. package/dist/gemini.cjs.map +1 -1
  146. package/dist/gemini.d.cts.map +1 -1
  147. package/dist/gemini.d.ts.map +1 -1
  148. package/dist/gemini.js +295 -219
  149. package/dist/gemini.js.map +1 -1
  150. package/dist/grok-video.cjs +14 -12
  151. package/dist/grok-video.cjs.map +1 -1
  152. package/dist/grok-video.d.cts.map +1 -1
  153. package/dist/grok-video.d.ts.map +1 -1
  154. package/dist/grok-video.js +8 -6
  155. package/dist/grok-video.js.map +1 -1
  156. package/dist/helpers.cjs +411 -75
  157. package/dist/helpers.cjs.map +1 -1
  158. package/dist/helpers.d.cts +51 -1
  159. package/dist/helpers.d.cts.map +1 -1
  160. package/dist/helpers.d.ts +51 -1
  161. package/dist/helpers.d.ts.map +1 -1
  162. package/dist/helpers.js +402 -74
  163. package/dist/helpers.js.map +1 -1
  164. package/dist/images.cjs +30 -28
  165. package/dist/images.cjs.map +1 -1
  166. package/dist/images.d.cts.map +1 -1
  167. package/dist/images.d.ts.map +1 -1
  168. package/dist/images.js +27 -25
  169. package/dist/images.js.map +1 -1
  170. package/dist/index.cjs +4 -2
  171. package/dist/index.d.cts +4 -4
  172. package/dist/index.d.ts +4 -4
  173. package/dist/index.js +4 -4
  174. package/dist/journal.cjs +3 -1
  175. package/dist/journal.cjs.map +1 -1
  176. package/dist/journal.d.cts.map +1 -1
  177. package/dist/journal.d.ts.map +1 -1
  178. package/dist/journal.js +2 -1
  179. package/dist/journal.js.map +1 -1
  180. package/dist/llmock.cjs +3 -0
  181. package/dist/llmock.cjs.map +1 -1
  182. package/dist/llmock.d.cts.map +1 -1
  183. package/dist/llmock.d.ts.map +1 -1
  184. package/dist/llmock.js +3 -0
  185. package/dist/llmock.js.map +1 -1
  186. package/dist/mcp-fakes.d.cts.map +1 -1
  187. package/dist/mcp-handler.cjs +7 -3
  188. package/dist/mcp-handler.cjs.map +1 -1
  189. package/dist/mcp-handler.js +7 -3
  190. package/dist/mcp-handler.js.map +1 -1
  191. package/dist/mcp-recorder.cjs +2 -1
  192. package/dist/mcp-recorder.cjs.map +1 -1
  193. package/dist/mcp-recorder.js +3 -2
  194. package/dist/mcp-recorder.js.map +1 -1
  195. package/dist/messages.cjs +235 -202
  196. package/dist/messages.cjs.map +1 -1
  197. package/dist/messages.d.cts.map +1 -1
  198. package/dist/messages.d.ts.map +1 -1
  199. package/dist/messages.js +234 -202
  200. package/dist/messages.js.map +1 -1
  201. package/dist/metrics.cjs +5 -2
  202. package/dist/metrics.cjs.map +1 -1
  203. package/dist/metrics.d.cts.map +1 -1
  204. package/dist/metrics.d.ts.map +1 -1
  205. package/dist/metrics.js +6 -3
  206. package/dist/metrics.js.map +1 -1
  207. package/dist/misbehavior.cjs +62 -3
  208. package/dist/misbehavior.cjs.map +1 -1
  209. package/dist/misbehavior.d.cts.map +1 -1
  210. package/dist/misbehavior.d.ts.map +1 -1
  211. package/dist/misbehavior.js +63 -4
  212. package/dist/misbehavior.js.map +1 -1
  213. package/dist/model-utils.cjs +1 -0
  214. package/dist/model-utils.cjs.map +1 -1
  215. package/dist/model-utils.js +1 -1
  216. package/dist/model-utils.js.map +1 -1
  217. package/dist/moderation.cjs +15 -12
  218. package/dist/moderation.cjs.map +1 -1
  219. package/dist/moderation.js +14 -11
  220. package/dist/moderation.js.map +1 -1
  221. package/dist/ndjson-writer.cjs +21 -23
  222. package/dist/ndjson-writer.cjs.map +1 -1
  223. package/dist/ndjson-writer.d.cts +0 -1
  224. package/dist/ndjson-writer.d.cts.map +1 -1
  225. package/dist/ndjson-writer.d.ts +0 -1
  226. package/dist/ndjson-writer.d.ts.map +1 -1
  227. package/dist/ndjson-writer.js +21 -24
  228. package/dist/ndjson-writer.js.map +1 -1
  229. package/dist/ollama.cjs +276 -210
  230. package/dist/ollama.cjs.map +1 -1
  231. package/dist/ollama.d.cts.map +1 -1
  232. package/dist/ollama.d.ts.map +1 -1
  233. package/dist/ollama.js +273 -207
  234. package/dist/ollama.js.map +1 -1
  235. package/dist/openapi.cjs +323 -3
  236. package/dist/openapi.cjs.map +1 -1
  237. package/dist/openapi.d.cts.map +1 -1
  238. package/dist/openapi.d.ts.map +1 -1
  239. package/dist/openapi.js +324 -4
  240. package/dist/openapi.js.map +1 -1
  241. package/dist/openrouter-chat.cjs +11 -155
  242. package/dist/openrouter-chat.cjs.map +1 -1
  243. package/dist/openrouter-chat.js +11 -155
  244. package/dist/openrouter-chat.js.map +1 -1
  245. package/dist/openrouter-video.cjs +51 -74
  246. package/dist/openrouter-video.cjs.map +1 -1
  247. package/dist/openrouter-video.d.cts.map +1 -1
  248. package/dist/openrouter-video.d.ts.map +1 -1
  249. package/dist/openrouter-video.js +37 -60
  250. package/dist/openrouter-video.js.map +1 -1
  251. package/dist/raw-validation.cjs +177 -0
  252. package/dist/raw-validation.cjs.map +1 -0
  253. package/dist/raw-validation.js +176 -0
  254. package/dist/raw-validation.js.map +1 -0
  255. package/dist/recorder.cjs +176 -95
  256. package/dist/recorder.cjs.map +1 -1
  257. package/dist/recorder.d.cts.map +1 -1
  258. package/dist/recorder.d.ts.map +1 -1
  259. package/dist/recorder.js +176 -95
  260. package/dist/recorder.js.map +1 -1
  261. package/dist/rerank.cjs +13 -11
  262. package/dist/rerank.cjs.map +1 -1
  263. package/dist/rerank.js +12 -10
  264. package/dist/rerank.js.map +1 -1
  265. package/dist/response/catalog/anthropic-page.cjs +39 -0
  266. package/dist/response/catalog/anthropic-page.cjs.map +1 -0
  267. package/dist/response/catalog/anthropic-page.js +38 -0
  268. package/dist/response/catalog/anthropic-page.js.map +1 -0
  269. package/dist/response/catalog/collect.cjs +61 -0
  270. package/dist/response/catalog/collect.cjs.map +1 -0
  271. package/dist/response/catalog/collect.js +59 -0
  272. package/dist/response/catalog/collect.js.map +1 -0
  273. package/dist/response/catalog/gemini-page.cjs +25 -0
  274. package/dist/response/catalog/gemini-page.cjs.map +1 -0
  275. package/dist/response/catalog/gemini-page.js +24 -0
  276. package/dist/response/catalog/gemini-page.js.map +1 -0
  277. package/dist/response/catalog/render.cjs +182 -0
  278. package/dist/response/catalog/render.cjs.map +1 -0
  279. package/dist/response/catalog/render.js +171 -0
  280. package/dist/response/catalog/render.js.map +1 -0
  281. package/dist/response/deliver.cjs +144 -0
  282. package/dist/response/deliver.cjs.map +1 -0
  283. package/dist/response/deliver.js +143 -0
  284. package/dist/response/deliver.js.map +1 -0
  285. package/dist/response/errors.cjs +225 -0
  286. package/dist/response/errors.cjs.map +1 -0
  287. package/dist/response/errors.js +224 -0
  288. package/dist/response/errors.js.map +1 -0
  289. package/dist/response/finish.cjs +39 -0
  290. package/dist/response/finish.cjs.map +1 -0
  291. package/dist/response/finish.js +35 -0
  292. package/dist/response/finish.js.map +1 -0
  293. package/dist/response/frame-loop.cjs +102 -0
  294. package/dist/response/frame-loop.cjs.map +1 -0
  295. package/dist/response/frame-loop.js +100 -0
  296. package/dist/response/frame-loop.js.map +1 -0
  297. package/dist/response/lifecycle.cjs +223 -0
  298. package/dist/response/lifecycle.cjs.map +1 -0
  299. package/dist/response/lifecycle.js +211 -0
  300. package/dist/response/lifecycle.js.map +1 -0
  301. package/dist/response/policy.cjs +126 -0
  302. package/dist/response/policy.cjs.map +1 -0
  303. package/dist/response/policy.js +120 -0
  304. package/dist/response/policy.js.map +1 -0
  305. package/dist/response/profiles.cjs +69 -0
  306. package/dist/response/profiles.cjs.map +1 -0
  307. package/dist/response/profiles.js +65 -0
  308. package/dist/response/profiles.js.map +1 -0
  309. package/dist/response/proxy.cjs +71 -0
  310. package/dist/response/proxy.cjs.map +1 -0
  311. package/dist/response/proxy.js +70 -0
  312. package/dist/response/proxy.js.map +1 -0
  313. package/dist/response/raw.cjs +228 -0
  314. package/dist/response/raw.cjs.map +1 -0
  315. package/dist/response/raw.js +227 -0
  316. package/dist/response/raw.js.map +1 -0
  317. package/dist/response/timing.cjs +157 -0
  318. package/dist/response/timing.cjs.map +1 -0
  319. package/dist/response/timing.js +150 -0
  320. package/dist/response/timing.js.map +1 -0
  321. package/dist/response/usage/codecs/anthropic.cjs +52 -0
  322. package/dist/response/usage/codecs/anthropic.cjs.map +1 -0
  323. package/dist/response/usage/codecs/anthropic.js +50 -0
  324. package/dist/response/usage/codecs/anthropic.js.map +1 -0
  325. package/dist/response/usage/codecs/cohere.cjs +36 -0
  326. package/dist/response/usage/codecs/cohere.cjs.map +1 -0
  327. package/dist/response/usage/codecs/cohere.js +35 -0
  328. package/dist/response/usage/codecs/cohere.js.map +1 -0
  329. package/dist/response/usage/codecs/converse.cjs +16 -0
  330. package/dist/response/usage/codecs/converse.cjs.map +1 -0
  331. package/dist/response/usage/codecs/converse.js +15 -0
  332. package/dist/response/usage/codecs/converse.js.map +1 -0
  333. package/dist/response/usage/codecs/gemini.cjs +31 -0
  334. package/dist/response/usage/codecs/gemini.cjs.map +1 -0
  335. package/dist/response/usage/codecs/gemini.js +31 -0
  336. package/dist/response/usage/codecs/gemini.js.map +1 -0
  337. package/dist/response/usage/codecs/interactions.cjs +22 -0
  338. package/dist/response/usage/codecs/interactions.cjs.map +1 -0
  339. package/dist/response/usage/codecs/interactions.js +21 -0
  340. package/dist/response/usage/codecs/interactions.js.map +1 -0
  341. package/dist/response/usage/codecs/ollama.cjs +17 -0
  342. package/dist/response/usage/codecs/ollama.cjs.map +1 -0
  343. package/dist/response/usage/codecs/ollama.js +17 -0
  344. package/dist/response/usage/codecs/ollama.js.map +1 -0
  345. package/dist/response/usage/codecs/openai.cjs +52 -0
  346. package/dist/response/usage/codecs/openai.cjs.map +1 -0
  347. package/dist/response/usage/codecs/openai.js +50 -0
  348. package/dist/response/usage/codecs/openai.js.map +1 -0
  349. package/dist/response/usage/codecs/openrouter.cjs +68 -0
  350. package/dist/response/usage/codecs/openrouter.cjs.map +1 -0
  351. package/dist/response/usage/codecs/openrouter.js +67 -0
  352. package/dist/response/usage/codecs/openrouter.js.map +1 -0
  353. package/dist/response/usage/codecs/realtime.cjs +19 -0
  354. package/dist/response/usage/codecs/realtime.cjs.map +1 -0
  355. package/dist/response/usage/codecs/realtime.js +18 -0
  356. package/dist/response/usage/codecs/realtime.js.map +1 -0
  357. package/dist/response/usage/codecs/responses.cjs +21 -0
  358. package/dist/response/usage/codecs/responses.cjs.map +1 -0
  359. package/dist/response/usage/codecs/responses.js +20 -0
  360. package/dist/response/usage/codecs/responses.js.map +1 -0
  361. package/dist/response/usage/estimate.cjs +23 -0
  362. package/dist/response/usage/estimate.cjs.map +1 -0
  363. package/dist/response/usage/estimate.js +21 -0
  364. package/dist/response/usage/estimate.js.map +1 -0
  365. package/dist/response/usage/fields.cjs +72 -0
  366. package/dist/response/usage/fields.cjs.map +1 -0
  367. package/dist/response/usage/fields.js +70 -0
  368. package/dist/response/usage/fields.js.map +1 -0
  369. package/dist/response/usage/recording.cjs +52 -0
  370. package/dist/response/usage/recording.cjs.map +1 -0
  371. package/dist/response/usage/recording.js +52 -0
  372. package/dist/response/usage/recording.js.map +1 -0
  373. package/dist/responses.cjs +304 -196
  374. package/dist/responses.cjs.map +1 -1
  375. package/dist/responses.d.cts.map +1 -1
  376. package/dist/responses.d.ts.map +1 -1
  377. package/dist/responses.js +303 -195
  378. package/dist/responses.js.map +1 -1
  379. package/dist/route-registry.cjs +45 -0
  380. package/dist/route-registry.cjs.map +1 -1
  381. package/dist/route-registry.d.cts.map +1 -1
  382. package/dist/route-registry.d.ts.map +1 -1
  383. package/dist/route-registry.js +41 -1
  384. package/dist/route-registry.js.map +1 -1
  385. package/dist/router.cjs +24 -4
  386. package/dist/router.cjs.map +1 -1
  387. package/dist/router.d.cts +7 -1
  388. package/dist/router.d.cts.map +1 -1
  389. package/dist/router.d.ts +7 -1
  390. package/dist/router.d.ts.map +1 -1
  391. package/dist/router.js +24 -5
  392. package/dist/router.js.map +1 -1
  393. package/dist/search.cjs +13 -11
  394. package/dist/search.cjs.map +1 -1
  395. package/dist/search.js +12 -10
  396. package/dist/search.js.map +1 -1
  397. package/dist/server.cjs +293 -248
  398. package/dist/server.cjs.map +1 -1
  399. package/dist/server.d.cts.map +1 -1
  400. package/dist/server.d.ts.map +1 -1
  401. package/dist/server.js +294 -249
  402. package/dist/server.js.map +1 -1
  403. package/dist/speech.cjs +20 -18
  404. package/dist/speech.cjs.map +1 -1
  405. package/dist/speech.d.cts.map +1 -1
  406. package/dist/speech.d.ts.map +1 -1
  407. package/dist/speech.js +19 -17
  408. package/dist/speech.js.map +1 -1
  409. package/dist/sse-writer.cjs +56 -30
  410. package/dist/sse-writer.cjs.map +1 -1
  411. package/dist/sse-writer.d.cts +0 -1
  412. package/dist/sse-writer.d.cts.map +1 -1
  413. package/dist/sse-writer.d.ts +0 -1
  414. package/dist/sse-writer.d.ts.map +1 -1
  415. package/dist/sse-writer.js +55 -31
  416. package/dist/sse-writer.js.map +1 -1
  417. package/dist/stream-collapse.cjs +118 -11
  418. package/dist/stream-collapse.cjs.map +1 -1
  419. package/dist/stream-collapse.d.cts +10 -9
  420. package/dist/stream-collapse.d.cts.map +1 -1
  421. package/dist/stream-collapse.d.ts +10 -9
  422. package/dist/stream-collapse.d.ts.map +1 -1
  423. package/dist/stream-collapse.js +118 -11
  424. package/dist/stream-collapse.js.map +1 -1
  425. package/dist/transcription.cjs +31 -43
  426. package/dist/transcription.cjs.map +1 -1
  427. package/dist/transcription.d.cts.map +1 -1
  428. package/dist/transcription.d.ts.map +1 -1
  429. package/dist/transcription.js +31 -43
  430. package/dist/transcription.js.map +1 -1
  431. package/dist/types.cjs.map +1 -1
  432. package/dist/types.d.cts +231 -9
  433. package/dist/types.d.cts.map +1 -1
  434. package/dist/types.d.ts +231 -9
  435. package/dist/types.d.ts.map +1 -1
  436. package/dist/types.js.map +1 -1
  437. package/dist/vector-mock.cjs +3 -8
  438. package/dist/vector-mock.cjs.map +1 -1
  439. package/dist/vector-mock.d.cts.map +1 -1
  440. package/dist/vector-mock.d.ts.map +1 -1
  441. package/dist/vector-mock.js +3 -8
  442. package/dist/vector-mock.js.map +1 -1
  443. package/dist/vector-stores.cjs +2 -4
  444. package/dist/vector-stores.cjs.map +1 -1
  445. package/dist/vector-stores.d.cts.map +1 -1
  446. package/dist/vector-stores.d.ts.map +1 -1
  447. package/dist/vector-stores.js +2 -4
  448. package/dist/vector-stores.js.map +1 -1
  449. package/dist/veo-video.cjs +16 -14
  450. package/dist/veo-video.cjs.map +1 -1
  451. package/dist/veo-video.js +10 -8
  452. package/dist/veo-video.js.map +1 -1
  453. package/dist/video.cjs +21 -19
  454. package/dist/video.cjs.map +1 -1
  455. package/dist/video.d.cts.map +1 -1
  456. package/dist/video.d.ts.map +1 -1
  457. package/dist/video.js +20 -18
  458. package/dist/video.js.map +1 -1
  459. package/dist/ws-framing.cjs +12 -6
  460. package/dist/ws-framing.cjs.map +1 -1
  461. package/dist/ws-framing.d.cts +2 -0
  462. package/dist/ws-framing.d.cts.map +1 -1
  463. package/dist/ws-framing.d.ts +2 -0
  464. package/dist/ws-framing.d.ts.map +1 -1
  465. package/dist/ws-framing.js +12 -6
  466. package/dist/ws-framing.js.map +1 -1
  467. package/dist/ws-gemini-live.cjs +131 -96
  468. package/dist/ws-gemini-live.cjs.map +1 -1
  469. package/dist/ws-gemini-live.d.cts +0 -1
  470. package/dist/ws-gemini-live.d.cts.map +1 -1
  471. package/dist/ws-gemini-live.d.ts +0 -1
  472. package/dist/ws-gemini-live.d.ts.map +1 -1
  473. package/dist/ws-gemini-live.js +130 -95
  474. package/dist/ws-gemini-live.js.map +1 -1
  475. package/dist/ws-live.cjs +6 -5
  476. package/dist/ws-live.cjs.map +1 -1
  477. package/dist/ws-live.js +5 -4
  478. package/dist/ws-live.js.map +1 -1
  479. package/dist/ws-realtime.cjs +108 -124
  480. package/dist/ws-realtime.cjs.map +1 -1
  481. package/dist/ws-realtime.d.cts.map +1 -1
  482. package/dist/ws-realtime.d.ts.map +1 -1
  483. package/dist/ws-realtime.js +105 -121
  484. package/dist/ws-realtime.js.map +1 -1
  485. package/dist/ws-responses.cjs +80 -59
  486. package/dist/ws-responses.cjs.map +1 -1
  487. package/dist/ws-responses.d.cts.map +1 -1
  488. package/dist/ws-responses.d.ts.map +1 -1
  489. package/dist/ws-responses.js +79 -58
  490. package/dist/ws-responses.js.map +1 -1
  491. package/package.json +4 -1
  492. package/skills/write-fixtures/SKILL.md +57 -16
@@ -0,0 +1,65 @@
1
+ //#region src/response/profiles.ts
2
+ /** Inbound HTTP auth uses only provider-owned paths; shared routes stay legacy. */
3
+ function authErrorDialectForPath(pathname) {
4
+ if (pathname === "/v1/messages" || pathname === "/v1/messages/count_tokens") return "messages";
5
+ if (pathname.startsWith("/v1beta/") || /^\/v1\/projects\/[^/]+\/locations\/[^/]+\/publishers\/google\//.test(pathname)) return "gemini";
6
+ return "openai";
7
+ }
8
+ /**
9
+ * Shared catalog response dialect. The list route uses it only under
10
+ * `policy.modelCatalog: "native"`. Auth retains its pathname-selected dialect.
11
+ */
12
+ function isAnthropicModelRequest(headers) {
13
+ return headers["anthropic-version"] !== void 0 || headers["x-api-key"] !== void 0 && headers.authorization === void 0;
14
+ }
15
+ /** Static wire facts only. Status selection and transport behavior belong to callers. */
16
+ const errorProfiles = {
17
+ openai: {
18
+ fixtureType: "server_error",
19
+ validationType: "invalid_request_error"
20
+ },
21
+ messages: {
22
+ fixtureType: "api_error",
23
+ validationType: "invalid_request_error",
24
+ requiredHeaders: ["anthropic-version"]
25
+ },
26
+ bedrock: {
27
+ fixtureType: "api_error",
28
+ validationType: "invalid_request_error",
29
+ toolArgumentType: "InternalServerException"
30
+ },
31
+ "bedrock-converse": {
32
+ fixtureType: "api_error",
33
+ validationType: "invalid_request_error",
34
+ toolArgumentType: "InternalServerException"
35
+ },
36
+ ollama: {
37
+ fixtureType: "server_error",
38
+ validationType: "invalid_request_error"
39
+ },
40
+ "ollama-embed": {
41
+ fixtureType: "server_error",
42
+ validationType: "invalid_request_error"
43
+ },
44
+ cohere: {
45
+ fixtureType: "server_error",
46
+ validationType: "invalid_request_error"
47
+ },
48
+ interactions: {
49
+ fixtureType: "server_error",
50
+ validationType: "invalid_request_error"
51
+ },
52
+ gemini: {
53
+ fixtureType: "server_error",
54
+ validationType: "invalid_request_error"
55
+ }
56
+ };
57
+ /** Bedrock's body-level version and other wire families have no header requirement. */
58
+ function missingRequiredHeader(wire, headers) {
59
+ if (wire !== "messages") return;
60
+ return errorProfiles.messages.requiredHeaders.find((name) => headers[name] === void 0);
61
+ }
62
+
63
+ //#endregion
64
+ export { authErrorDialectForPath, errorProfiles, isAnthropicModelRequest, missingRequiredHeader };
65
+ //# sourceMappingURL=profiles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profiles.js","names":[],"sources":["../../src/response/profiles.ts"],"sourcesContent":["import type { IncomingHttpHeaders } from \"node:http\";\n\n/** Inbound HTTP auth uses only provider-owned paths; shared routes stay legacy. */\nexport function authErrorDialectForPath(pathname: string): \"messages\" | \"gemini\" | \"openai\" {\n if (pathname === \"/v1/messages\" || pathname === \"/v1/messages/count_tokens\") return \"messages\";\n if (\n pathname.startsWith(\"/v1beta/\") ||\n /^\\/v1\\/projects\\/[^/]+\\/locations\\/[^/]+\\/publishers\\/google\\//.test(pathname)\n )\n return \"gemini\";\n return \"openai\";\n}\n\n/**\n * Shared catalog response dialect. The list route uses it only under\n * `policy.modelCatalog: \"native\"`. Auth retains its pathname-selected dialect.\n */\nexport function isAnthropicModelRequest(headers: IncomingHttpHeaders): boolean {\n return (\n headers[\"anthropic-version\"] !== undefined ||\n (headers[\"x-api-key\"] !== undefined && headers.authorization === undefined)\n );\n}\n\n/** Static wire facts only. Status selection and transport behavior belong to callers. */\nexport const errorProfiles = {\n openai: { fixtureType: \"server_error\", validationType: \"invalid_request_error\" },\n messages: {\n fixtureType: \"api_error\",\n validationType: \"invalid_request_error\",\n requiredHeaders: [\"anthropic-version\"],\n },\n bedrock: {\n fixtureType: \"api_error\",\n validationType: \"invalid_request_error\",\n toolArgumentType: \"InternalServerException\",\n },\n \"bedrock-converse\": {\n fixtureType: \"api_error\",\n validationType: \"invalid_request_error\",\n toolArgumentType: \"InternalServerException\",\n },\n ollama: { fixtureType: \"server_error\", validationType: \"invalid_request_error\" },\n \"ollama-embed\": { fixtureType: \"server_error\", validationType: \"invalid_request_error\" },\n cohere: { fixtureType: \"server_error\", validationType: \"invalid_request_error\" },\n interactions: { fixtureType: \"server_error\", validationType: \"invalid_request_error\" },\n gemini: { fixtureType: \"server_error\", validationType: \"invalid_request_error\" },\n} as const;\n\nexport type ErrorWire = keyof typeof errorProfiles;\n\n/** Bedrock's body-level version and other wire families have no header requirement. */\nexport function missingRequiredHeader(\n wire: ErrorWire,\n headers: IncomingHttpHeaders,\n): string | undefined {\n if (wire !== \"messages\") return;\n return errorProfiles.messages.requiredHeaders.find((name) => headers[name] === undefined);\n}\n"],"mappings":";;AAGA,SAAgB,wBAAwB,UAAoD;AAC1F,KAAI,aAAa,kBAAkB,aAAa,4BAA6B,QAAO;AACpF,KACE,SAAS,WAAW,WAAW,IAC/B,iEAAiE,KAAK,SAAS,CAE/E,QAAO;AACT,QAAO;;;;;;AAOT,SAAgB,wBAAwB,SAAuC;AAC7E,QACE,QAAQ,yBAAyB,UAChC,QAAQ,iBAAiB,UAAa,QAAQ,kBAAkB;;;AAKrE,MAAa,gBAAgB;CAC3B,QAAQ;EAAE,aAAa;EAAgB,gBAAgB;EAAyB;CAChF,UAAU;EACR,aAAa;EACb,gBAAgB;EAChB,iBAAiB,CAAC,oBAAoB;EACvC;CACD,SAAS;EACP,aAAa;EACb,gBAAgB;EAChB,kBAAkB;EACnB;CACD,oBAAoB;EAClB,aAAa;EACb,gBAAgB;EAChB,kBAAkB;EACnB;CACD,QAAQ;EAAE,aAAa;EAAgB,gBAAgB;EAAyB;CAChF,gBAAgB;EAAE,aAAa;EAAgB,gBAAgB;EAAyB;CACxF,QAAQ;EAAE,aAAa;EAAgB,gBAAgB;EAAyB;CAChF,cAAc;EAAE,aAAa;EAAgB,gBAAgB;EAAyB;CACtF,QAAQ;EAAE,aAAa;EAAgB,gBAAgB;EAAyB;CACjF;;AAKD,SAAgB,sBACd,MACA,SACoB;AACpB,KAAI,SAAS,WAAY;AACzB,QAAO,cAAc,SAAS,gBAAgB,MAAM,SAAS,QAAQ,UAAU,OAAU"}
@@ -0,0 +1,71 @@
1
+ const require_lifecycle = require('./lifecycle.cjs');
2
+
3
+ //#region src/response/proxy.ts
4
+ /**
5
+ * Responses torn down before they finished, judged at entry, on `close`, and
6
+ * when the relay returns. Reading `res.writableFinished` only when journaling
7
+ * is too late: on Node 20 and 22 a relay that calls `end()` on a destroyed
8
+ * response makes it read `true` (Node 24+ keeps it `false`).
9
+ */
10
+ const tornDownBeforeFinish = /* @__PURE__ */ new WeakSet();
11
+ /**
12
+ * Run a proxy relay while watching for a client hang-up.
13
+ *
14
+ * WHO killed a mid-flight stream decides what the journal says, and after the
15
+ * fact the two look identical: `req.aborted`, `req.destroyed` and
16
+ * `res.destroyed` all read the same whether the peer hung up or the recorder
17
+ * tore the response down. So the hang-up is decided when the request socket
18
+ * actually closes before the response ended, by the same rule the delivery
19
+ * lifecycle uses ({@link teardownCause}): the client's socket closed or reset.
20
+ * A FIN alone is not a hang-up. A response already gone when this is entered
21
+ * is judged by that rule too, so a response aimock destroyed is not blamed on
22
+ * the client. The listener is attached before `run` and removed after it: a
23
+ * keep-alive socket outlives this request.
24
+ */
25
+ async function withHangUpDetection(req, res, run) {
26
+ const socket = req.socket;
27
+ require_lifecycle.noteDeliveryStart(res);
28
+ const clientCaused = () => !res.writableEnded && require_lifecycle.teardownCause(res, socket) === "client";
29
+ let clientHungUp = (res.destroyed || socket?.destroyed === true) && clientCaused();
30
+ const noteSocketClose = () => {
31
+ if (clientCaused()) clientHungUp = true;
32
+ };
33
+ const noteTearDown = () => {
34
+ if (res.destroyed && !res.writableFinished) tornDownBeforeFinish.add(res);
35
+ };
36
+ noteTearDown();
37
+ socket?.on("close", noteSocketClose);
38
+ res.on("close", noteTearDown);
39
+ try {
40
+ return {
41
+ outcome: await run(),
42
+ clientHungUp
43
+ };
44
+ } finally {
45
+ noteTearDown();
46
+ socket?.off("close", noteSocketClose);
47
+ res.off("close", noteTearDown);
48
+ }
49
+ }
50
+ /**
51
+ * The journal fields for a proxied response. A stream torn down before it
52
+ * finished (destroyed, even when the relay called `end()` on it afterwards)
53
+ * is marked interrupted and names the side that killed it: a client hang-up
54
+ * is normal caller behaviour, an upstream/recorder tear-down is a fault worth
55
+ * chasing. When no byte of the response reached the socket
56
+ * ({@link statusLineSent}) the status is 0: the client never got a status
57
+ * line. A response that finished, or was never torn down, gets no fields.
58
+ */
59
+ function proxyInterruption(res, clientHungUp) {
60
+ if (!(res.destroyed && (tornDownBeforeFinish.has(res) || !res.writableFinished))) return {};
61
+ return {
62
+ ...require_lifecycle.statusLineSent(res) ? {} : { status: 0 },
63
+ interrupted: true,
64
+ interruptReason: clientHungUp ? require_lifecycle.CLIENT_ABORTED : "proxy stream destroyed"
65
+ };
66
+ }
67
+
68
+ //#endregion
69
+ exports.proxyInterruption = proxyInterruption;
70
+ exports.withHangUpDetection = withHangUpDetection;
71
+ //# sourceMappingURL=proxy.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy.cjs","names":["teardownCause","statusLineSent","CLIENT_ABORTED"],"sources":["../../src/response/proxy.ts"],"sourcesContent":["import type * as http from \"node:http\";\nimport { CLIENT_ABORTED, noteDeliveryStart, statusLineSent, teardownCause } from \"./lifecycle.js\";\n\n/**\n * Responses torn down before they finished, judged at entry, on `close`, and\n * when the relay returns. Reading `res.writableFinished` only when journaling\n * is too late: on Node 20 and 22 a relay that calls `end()` on a destroyed\n * response makes it read `true` (Node 24+ keeps it `false`).\n */\nconst tornDownBeforeFinish = new WeakSet<http.ServerResponse>();\n\n/**\n * Run a proxy relay while watching for a client hang-up.\n *\n * WHO killed a mid-flight stream decides what the journal says, and after the\n * fact the two look identical: `req.aborted`, `req.destroyed` and\n * `res.destroyed` all read the same whether the peer hung up or the recorder\n * tore the response down. So the hang-up is decided when the request socket\n * actually closes before the response ended, by the same rule the delivery\n * lifecycle uses ({@link teardownCause}): the client's socket closed or reset.\n * A FIN alone is not a hang-up. A response already gone when this is entered\n * is judged by that rule too, so a response aimock destroyed is not blamed on\n * the client. The listener is attached before `run` and removed after it: a\n * keep-alive socket outlives this request.\n */\nexport async function withHangUpDetection<T>(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n run: () => Promise<T>,\n): Promise<{ outcome: T; clientHungUp: boolean }> {\n const socket = req.socket;\n noteDeliveryStart(res);\n const clientCaused = (): boolean => !res.writableEnded && teardownCause(res, socket) === \"client\";\n let clientHungUp = (res.destroyed || socket?.destroyed === true) && clientCaused();\n const noteSocketClose = (): void => {\n if (clientCaused()) clientHungUp = true;\n };\n const noteTearDown = (): void => {\n if (res.destroyed && !res.writableFinished) tornDownBeforeFinish.add(res);\n };\n noteTearDown();\n socket?.on(\"close\", noteSocketClose);\n res.on(\"close\", noteTearDown);\n try {\n const outcome = await run();\n return { outcome, clientHungUp };\n } finally {\n // The relay may have destroyed the response in its last tick, before\n // `close` is emitted.\n noteTearDown();\n socket?.off(\"close\", noteSocketClose);\n res.off(\"close\", noteTearDown);\n }\n}\n\n/**\n * The journal fields for a proxied response. A stream torn down before it\n * finished (destroyed, even when the relay called `end()` on it afterwards)\n * is marked interrupted and names the side that killed it: a client hang-up\n * is normal caller behaviour, an upstream/recorder tear-down is a fault worth\n * chasing. When no byte of the response reached the socket\n * ({@link statusLineSent}) the status is 0: the client never got a status\n * line. A response that finished, or was never torn down, gets no fields.\n */\nexport function proxyInterruption(\n res: http.ServerResponse,\n clientHungUp: boolean,\n): { status?: 0; interrupted?: true; interruptReason?: string } {\n const tornDown = res.destroyed && (tornDownBeforeFinish.has(res) || !res.writableFinished);\n if (!tornDown) return {};\n return {\n ...(statusLineSent(res) ? {} : { status: 0 as const }),\n interrupted: true,\n interruptReason: clientHungUp ? CLIENT_ABORTED : \"proxy stream destroyed\",\n };\n}\n"],"mappings":";;;;;;;;;AASA,MAAM,uCAAuB,IAAI,SAA8B;;;;;;;;;;;;;;;AAgB/D,eAAsB,oBACpB,KACA,KACA,KACgD;CAChD,MAAM,SAAS,IAAI;AACnB,qCAAkB,IAAI;CACtB,MAAM,qBAA8B,CAAC,IAAI,iBAAiBA,gCAAc,KAAK,OAAO,KAAK;CACzF,IAAI,gBAAgB,IAAI,aAAa,QAAQ,cAAc,SAAS,cAAc;CAClF,MAAM,wBAA8B;AAClC,MAAI,cAAc,CAAE,gBAAe;;CAErC,MAAM,qBAA2B;AAC/B,MAAI,IAAI,aAAa,CAAC,IAAI,iBAAkB,sBAAqB,IAAI,IAAI;;AAE3E,eAAc;AACd,SAAQ,GAAG,SAAS,gBAAgB;AACpC,KAAI,GAAG,SAAS,aAAa;AAC7B,KAAI;AAEF,SAAO;GAAE,SADO,MAAM,KAAK;GACT;GAAc;WACxB;AAGR,gBAAc;AACd,UAAQ,IAAI,SAAS,gBAAgB;AACrC,MAAI,IAAI,SAAS,aAAa;;;;;;;;;;;;AAalC,SAAgB,kBACd,KACA,cAC8D;AAE9D,KAAI,EADa,IAAI,cAAc,qBAAqB,IAAI,IAAI,IAAI,CAAC,IAAI,mBAC1D,QAAO,EAAE;AACxB,QAAO;EACL,GAAIC,iCAAe,IAAI,GAAG,EAAE,GAAG,EAAE,QAAQ,GAAY;EACrD,aAAa;EACb,iBAAiB,eAAeC,mCAAiB;EAClD"}
@@ -0,0 +1,70 @@
1
+ import { CLIENT_ABORTED, noteDeliveryStart, statusLineSent, teardownCause } from "./lifecycle.js";
2
+
3
+ //#region src/response/proxy.ts
4
+ /**
5
+ * Responses torn down before they finished, judged at entry, on `close`, and
6
+ * when the relay returns. Reading `res.writableFinished` only when journaling
7
+ * is too late: on Node 20 and 22 a relay that calls `end()` on a destroyed
8
+ * response makes it read `true` (Node 24+ keeps it `false`).
9
+ */
10
+ const tornDownBeforeFinish = /* @__PURE__ */ new WeakSet();
11
+ /**
12
+ * Run a proxy relay while watching for a client hang-up.
13
+ *
14
+ * WHO killed a mid-flight stream decides what the journal says, and after the
15
+ * fact the two look identical: `req.aborted`, `req.destroyed` and
16
+ * `res.destroyed` all read the same whether the peer hung up or the recorder
17
+ * tore the response down. So the hang-up is decided when the request socket
18
+ * actually closes before the response ended, by the same rule the delivery
19
+ * lifecycle uses ({@link teardownCause}): the client's socket closed or reset.
20
+ * A FIN alone is not a hang-up. A response already gone when this is entered
21
+ * is judged by that rule too, so a response aimock destroyed is not blamed on
22
+ * the client. The listener is attached before `run` and removed after it: a
23
+ * keep-alive socket outlives this request.
24
+ */
25
+ async function withHangUpDetection(req, res, run) {
26
+ const socket = req.socket;
27
+ noteDeliveryStart(res);
28
+ const clientCaused = () => !res.writableEnded && teardownCause(res, socket) === "client";
29
+ let clientHungUp = (res.destroyed || socket?.destroyed === true) && clientCaused();
30
+ const noteSocketClose = () => {
31
+ if (clientCaused()) clientHungUp = true;
32
+ };
33
+ const noteTearDown = () => {
34
+ if (res.destroyed && !res.writableFinished) tornDownBeforeFinish.add(res);
35
+ };
36
+ noteTearDown();
37
+ socket?.on("close", noteSocketClose);
38
+ res.on("close", noteTearDown);
39
+ try {
40
+ return {
41
+ outcome: await run(),
42
+ clientHungUp
43
+ };
44
+ } finally {
45
+ noteTearDown();
46
+ socket?.off("close", noteSocketClose);
47
+ res.off("close", noteTearDown);
48
+ }
49
+ }
50
+ /**
51
+ * The journal fields for a proxied response. A stream torn down before it
52
+ * finished (destroyed, even when the relay called `end()` on it afterwards)
53
+ * is marked interrupted and names the side that killed it: a client hang-up
54
+ * is normal caller behaviour, an upstream/recorder tear-down is a fault worth
55
+ * chasing. When no byte of the response reached the socket
56
+ * ({@link statusLineSent}) the status is 0: the client never got a status
57
+ * line. A response that finished, or was never torn down, gets no fields.
58
+ */
59
+ function proxyInterruption(res, clientHungUp) {
60
+ if (!(res.destroyed && (tornDownBeforeFinish.has(res) || !res.writableFinished))) return {};
61
+ return {
62
+ ...statusLineSent(res) ? {} : { status: 0 },
63
+ interrupted: true,
64
+ interruptReason: clientHungUp ? CLIENT_ABORTED : "proxy stream destroyed"
65
+ };
66
+ }
67
+
68
+ //#endregion
69
+ export { proxyInterruption, withHangUpDetection };
70
+ //# sourceMappingURL=proxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy.js","names":[],"sources":["../../src/response/proxy.ts"],"sourcesContent":["import type * as http from \"node:http\";\nimport { CLIENT_ABORTED, noteDeliveryStart, statusLineSent, teardownCause } from \"./lifecycle.js\";\n\n/**\n * Responses torn down before they finished, judged at entry, on `close`, and\n * when the relay returns. Reading `res.writableFinished` only when journaling\n * is too late: on Node 20 and 22 a relay that calls `end()` on a destroyed\n * response makes it read `true` (Node 24+ keeps it `false`).\n */\nconst tornDownBeforeFinish = new WeakSet<http.ServerResponse>();\n\n/**\n * Run a proxy relay while watching for a client hang-up.\n *\n * WHO killed a mid-flight stream decides what the journal says, and after the\n * fact the two look identical: `req.aborted`, `req.destroyed` and\n * `res.destroyed` all read the same whether the peer hung up or the recorder\n * tore the response down. So the hang-up is decided when the request socket\n * actually closes before the response ended, by the same rule the delivery\n * lifecycle uses ({@link teardownCause}): the client's socket closed or reset.\n * A FIN alone is not a hang-up. A response already gone when this is entered\n * is judged by that rule too, so a response aimock destroyed is not blamed on\n * the client. The listener is attached before `run` and removed after it: a\n * keep-alive socket outlives this request.\n */\nexport async function withHangUpDetection<T>(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n run: () => Promise<T>,\n): Promise<{ outcome: T; clientHungUp: boolean }> {\n const socket = req.socket;\n noteDeliveryStart(res);\n const clientCaused = (): boolean => !res.writableEnded && teardownCause(res, socket) === \"client\";\n let clientHungUp = (res.destroyed || socket?.destroyed === true) && clientCaused();\n const noteSocketClose = (): void => {\n if (clientCaused()) clientHungUp = true;\n };\n const noteTearDown = (): void => {\n if (res.destroyed && !res.writableFinished) tornDownBeforeFinish.add(res);\n };\n noteTearDown();\n socket?.on(\"close\", noteSocketClose);\n res.on(\"close\", noteTearDown);\n try {\n const outcome = await run();\n return { outcome, clientHungUp };\n } finally {\n // The relay may have destroyed the response in its last tick, before\n // `close` is emitted.\n noteTearDown();\n socket?.off(\"close\", noteSocketClose);\n res.off(\"close\", noteTearDown);\n }\n}\n\n/**\n * The journal fields for a proxied response. A stream torn down before it\n * finished (destroyed, even when the relay called `end()` on it afterwards)\n * is marked interrupted and names the side that killed it: a client hang-up\n * is normal caller behaviour, an upstream/recorder tear-down is a fault worth\n * chasing. When no byte of the response reached the socket\n * ({@link statusLineSent}) the status is 0: the client never got a status\n * line. A response that finished, or was never torn down, gets no fields.\n */\nexport function proxyInterruption(\n res: http.ServerResponse,\n clientHungUp: boolean,\n): { status?: 0; interrupted?: true; interruptReason?: string } {\n const tornDown = res.destroyed && (tornDownBeforeFinish.has(res) || !res.writableFinished);\n if (!tornDown) return {};\n return {\n ...(statusLineSent(res) ? {} : { status: 0 as const }),\n interrupted: true,\n interruptReason: clientHungUp ? CLIENT_ABORTED : \"proxy stream destroyed\",\n };\n}\n"],"mappings":";;;;;;;;;AASA,MAAM,uCAAuB,IAAI,SAA8B;;;;;;;;;;;;;;;AAgB/D,eAAsB,oBACpB,KACA,KACA,KACgD;CAChD,MAAM,SAAS,IAAI;AACnB,mBAAkB,IAAI;CACtB,MAAM,qBAA8B,CAAC,IAAI,iBAAiB,cAAc,KAAK,OAAO,KAAK;CACzF,IAAI,gBAAgB,IAAI,aAAa,QAAQ,cAAc,SAAS,cAAc;CAClF,MAAM,wBAA8B;AAClC,MAAI,cAAc,CAAE,gBAAe;;CAErC,MAAM,qBAA2B;AAC/B,MAAI,IAAI,aAAa,CAAC,IAAI,iBAAkB,sBAAqB,IAAI,IAAI;;AAE3E,eAAc;AACd,SAAQ,GAAG,SAAS,gBAAgB;AACpC,KAAI,GAAG,SAAS,aAAa;AAC7B,KAAI;AAEF,SAAO;GAAE,SADO,MAAM,KAAK;GACT;GAAc;WACxB;AAGR,gBAAc;AACd,UAAQ,IAAI,SAAS,gBAAgB;AACrC,MAAI,IAAI,SAAS,aAAa;;;;;;;;;;;;AAalC,SAAgB,kBACd,KACA,cAC8D;AAE9D,KAAI,EADa,IAAI,cAAc,qBAAqB,IAAI,IAAI,IAAI,CAAC,IAAI,mBAC1D,QAAO,EAAE;AACxB,QAAO;EACL,GAAI,eAAe,IAAI,GAAG,EAAE,GAAG,EAAE,QAAQ,GAAY;EACrD,aAAa;EACb,iBAAiB,eAAe,iBAAiB;EAClD"}
@@ -0,0 +1,228 @@
1
+ const require_errors = require('./errors.cjs');
2
+ const require_helpers = require('../helpers.cjs');
3
+ const require_raw_validation = require('../raw-validation.cjs');
4
+ const require_sse_writer = require('../sse-writer.cjs');
5
+ const require_misbehavior = require('../misbehavior.cjs');
6
+ const require_fixture_loader = require('../fixture-loader.cjs');
7
+ const require_deliver = require('./deliver.cjs');
8
+ const require_aws_event_stream = require('../aws-event-stream.cjs');
9
+ const require_openrouter_chat = require('../openrouter-chat.cjs');
10
+ const require_ndjson_writer = require('../ndjson-writer.cjs');
11
+
12
+ //#region src/response/raw.ts
13
+ /**
14
+ * The default headers of the typed stream on `wire`, read from the typed
15
+ * codec: SSE and NDJSON add `Cache-Control: no-cache` and
16
+ * `Connection: keep-alive`, the AWS event stream `Transfer-Encoding: chunked`.
17
+ */
18
+ function rawStreamHeaders(wire) {
19
+ switch (wire) {
20
+ case "openai-responses":
21
+ case "openai-chat":
22
+ case "anthropic":
23
+ case "gemini":
24
+ case "gemini-interactions":
25
+ case "cohere": return require_sse_writer.sseCodec({ done: false }).headers;
26
+ case "ollama":
27
+ case "ollama-generate": return require_ndjson_writer.ndjsonCodec().headers;
28
+ case "bedrock-invoke":
29
+ case "bedrock-converse": return require_aws_event_stream.eventStreamCodec().headers;
30
+ }
31
+ }
32
+ /** The non-streaming JSON default, as `deliverJson` sends it. */
33
+ const JSON_HEADERS = { "Content-Type": "application/json" };
34
+ /**
35
+ * `defaults` with each `authored` header laid over it. Header names are
36
+ * case-insensitive: an authored header replaces the default of the same name
37
+ * in any letter case and takes the default's spelling, so a later spread over
38
+ * the same defaults (as `deliverJson` does) still has one key per name.
39
+ */
40
+ function overrideHeaders(defaults, authored) {
41
+ const merged = { ...defaults };
42
+ const spelling = new Map(Object.keys(defaults).map((name) => [name.toLowerCase(), name]));
43
+ for (const [name, value] of Object.entries(authored ?? {})) merged[spelling.get(name.toLowerCase()) ?? name] = value;
44
+ return merged;
45
+ }
46
+ /** One raw event, framed for `wire`. Events are checked before framing (raw-validation.ts). */
47
+ function encodeRawFrame(wire, event) {
48
+ const json = JSON.stringify(event);
49
+ switch (wire) {
50
+ case "openai-responses":
51
+ case "anthropic":
52
+ case "cohere": return `event: ${String(event.type)}\ndata: ${json}\n\n`;
53
+ case "openai-chat":
54
+ case "gemini":
55
+ case "gemini-interactions": return `data: ${json}\n\n`;
56
+ case "ollama":
57
+ case "ollama-generate": return `${json}\n`;
58
+ case "bedrock-invoke": return require_aws_event_stream.encodeEventStreamMessage("chunk", { bytes: Buffer.from(json, "utf8").toString("base64") });
59
+ case "bedrock-converse": {
60
+ const [eventType] = Object.keys(event);
61
+ const payload = event[eventType];
62
+ if (payload === null || typeof payload !== "object" || Array.isArray(payload)) throw new Error(`raw framing internal error: bedrock-converse event "${eventType}" has no object payload`);
63
+ return require_aws_event_stream.encodeEventStreamMessage(eventType, payload);
64
+ }
65
+ }
66
+ }
67
+ /**
68
+ * Bytes written after the last frame, if any. Only `openai-chat` has a
69
+ * terminal (`data: [DONE]`), sent unless `raw.done === false` and never after
70
+ * an interrupted stream.
71
+ */
72
+ function rawTrailer(wire, raw, aborted) {
73
+ if (wire === "openai-chat" && !aborted && raw.done !== false) return "data: [DONE]\n\n";
74
+ }
75
+ /** The error code for a request the raw fixture has no body for. */
76
+ const RAW_MODE_UNAVAILABLE = "aimock_raw_mode_unavailable";
77
+ /** The error code for a raw fixture that fails its checks or targets another wire. */
78
+ const RAW_FIXTURE_INVALID = "aimock_raw_fixture_invalid";
79
+ /**
80
+ * The raw events as a frame codec for the shared frame loop. Its headers are
81
+ * the typed stream's defaults for `wire` with `raw.headers` laid over them.
82
+ */
83
+ function rawCodec(wire, raw) {
84
+ return {
85
+ headers: overrideHeaders(rawStreamHeaders(wire), raw.headers),
86
+ encode: (event) => encodeRawFrame(wire, event),
87
+ trailer: (aborted) => {
88
+ const trailer = rawTrailer(wire, raw, aborted);
89
+ return trailer === void 0 ? [] : [trailer];
90
+ }
91
+ };
92
+ }
93
+ /**
94
+ * The error body for a raw 500, in the dialect of the handler's misbehavior
95
+ * errors. Dialects with no code slot (Gemini, Ollama, OpenRouter) carry the
96
+ * code as a message prefix.
97
+ */
98
+ function renderRawError(ctx, code, message) {
99
+ if (ctx.openRouter) return { body: require_openrouter_chat.serializeOpenRouterError(500, `${code}: ${message}`) };
100
+ switch (ctx.errorWire) {
101
+ case "openai": return require_errors.renderError("openai", "misbehavior", {
102
+ message,
103
+ type: "server_error",
104
+ ...ctx.wire === "openai-chat" ? {
105
+ param: null,
106
+ includeParam: true
107
+ } : {},
108
+ code
109
+ });
110
+ case "messages": return require_errors.renderError("messages", "misbehavior", {
111
+ type: "api_error",
112
+ code,
113
+ message
114
+ });
115
+ case "gemini": return require_errors.renderError("gemini", "misbehavior", {
116
+ bodyCode: 500,
117
+ message: `${code}: ${message}`,
118
+ status: "INTERNAL"
119
+ });
120
+ case "bedrock":
121
+ case "bedrock-converse": return require_errors.renderError(ctx.errorWire, "misbehavior", {
122
+ type: "InternalServerException",
123
+ code,
124
+ message
125
+ });
126
+ default: return require_errors.renderError(ctx.errorWire, "misbehavior", {
127
+ code,
128
+ message
129
+ });
130
+ }
131
+ }
132
+ /**
133
+ * Serve a raw passthrough fixture on the handler's wire: check it, journal it,
134
+ * and send its events or JSON through the shared delivery layer. A fixture
135
+ * that fails a check, targets another wire, or has no body for the requested
136
+ * mode gets a 500 in the handler's misbehavior error dialect, and an error log
137
+ * line. A reply with status 400 or more is never delayed, streaming or not,
138
+ * and one with `json` answers in JSON even to a streaming request.
139
+ */
140
+ async function serveRawResponse(ctx) {
141
+ const { wire, stream, req, res, fixture, journal, defaults, testId } = ctx;
142
+ const raw = ctx.response.raw;
143
+ const journalBase = {
144
+ method: req.method ?? "POST",
145
+ path: req.url ?? "/",
146
+ headers: require_helpers.flattenHeaders(req.headers),
147
+ body: ctx.body
148
+ };
149
+ const record = (entry) => require_misbehavior.recordMisbehaviorOutcome({
150
+ entry,
151
+ summary: ctx.misbehaviorSummary,
152
+ defaults,
153
+ testId
154
+ });
155
+ const status = raw.status ?? 200;
156
+ const errorReply = status >= 400;
157
+ const servesStream = stream && !(errorReply && raw.json !== void 0);
158
+ let failure;
159
+ const problems = require_raw_validation.checkRawResponse(raw, require_fixture_loader.rawFixtureContext(fixture, ctx.response)).filter((finding) => finding.severity === "error");
160
+ if (problems.length > 0) failure = {
161
+ code: RAW_FIXTURE_INVALID,
162
+ message: `invalid raw fixture: ${problems.map((p) => p.message).join("; ")}`
163
+ };
164
+ else if (raw.wire !== wire) failure = {
165
+ code: RAW_FIXTURE_INVALID,
166
+ message: `raw fixture is for ${raw.wire}, not ${wire}`
167
+ };
168
+ else if (servesStream ? raw.events === void 0 : raw.json === void 0) failure = {
169
+ code: RAW_MODE_UNAVAILABLE,
170
+ message: `raw fixture has no "${servesStream ? "events" : "json"}" body for a ${servesStream ? "streaming" : "non-streaming"} request on ${wire}`
171
+ };
172
+ if (failure) {
173
+ defaults.logger.error(`${journalBase.method} ${journalBase.path}: ${failure.message}`);
174
+ const entry = journal.add({
175
+ ...journalBase,
176
+ response: {
177
+ status: 500,
178
+ fixture
179
+ }
180
+ });
181
+ entry.response.error = failure.message;
182
+ record(entry);
183
+ const rendered = renderRawError(ctx, failure.code, failure.message);
184
+ for (const [name, value] of Object.entries(rendered.headers ?? {})) res.setHeader(name, value);
185
+ require_sse_writer.writeErrorResponse(res, 500, rendered.body);
186
+ return;
187
+ }
188
+ const entry = journal.add({
189
+ ...journalBase,
190
+ response: {
191
+ status,
192
+ fixture
193
+ }
194
+ });
195
+ record(entry);
196
+ if (servesStream) {
197
+ const events = raw.events;
198
+ if (events === void 0) throw new Error(`raw serve internal error: a streamed reply on ${wire} has no events`);
199
+ await require_deliver.deliverStream(res, entry, fixture, rawCodec(wire, raw), events, errorReply ? { latency: 0 } : {
200
+ latency: fixture.latency ?? defaults.latency,
201
+ streamingProfile: fixture.streamingProfile,
202
+ recordedTimings: fixture.recordedTimings,
203
+ replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed
204
+ }, { status: raw.status });
205
+ return;
206
+ }
207
+ const json = raw.json;
208
+ if (json === void 0) throw new Error(`raw serve internal error: a JSON reply on ${wire} has no json`);
209
+ const servedLength = JSON.stringify(json).length;
210
+ await require_deliver.deliverJson(res, entry, errorReply ? {
211
+ ...fixture,
212
+ nonStreamingTiming: false,
213
+ nonStreamingTimingAllProviders: false
214
+ } : fixture, () => json, {
215
+ surface: wire === "openai-chat" ? "openai-chat" : "other",
216
+ status: raw.status,
217
+ payloadLength: servedLength,
218
+ chunkSize: Math.max(1, fixture.chunkSize ?? defaults.chunkSize),
219
+ recordedTimings: fixture.recordedTimings,
220
+ replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed,
221
+ headers: overrideHeaders(JSON_HEADERS, raw.headers)
222
+ });
223
+ }
224
+
225
+ //#endregion
226
+ exports.RAW_MODE_UNAVAILABLE = RAW_MODE_UNAVAILABLE;
227
+ exports.serveRawResponse = serveRawResponse;
228
+ //# sourceMappingURL=raw.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"raw.cjs","names":["sseCodec","ndjsonCodec","eventStreamCodec","encodeEventStreamMessage","serializeOpenRouterError","renderError","flattenHeaders","recordMisbehaviorOutcome","checkRawResponse","rawFixtureContext","deliverStream","deliverJson"],"sources":["../../src/response/raw.ts"],"sourcesContent":["/**\n * @internal Raw passthrough fixtures (#549): per-wire framing and serving.\n *\n * A raw fixture supplies event objects; aimock adds only the named wire's\n * framing, using exactly the bytes the typed handlers write for that wire:\n *\n * - named SSE (`openai-responses`, `anthropic`, `cohere`):\n * `event: <type>\\ndata: <json>\\n\\n`\n * - data SSE (`openai-chat`, `gemini`, `gemini-interactions`): `data: <json>\\n\\n`;\n * `openai-chat` ends with `data: [DONE]\\n\\n` unless `raw.done === false`\n * - NDJSON (`ollama`, `ollama-generate`): `<json>\\n`\n * - AWS event stream: `bedrock-invoke` wraps each event as a `chunk` frame with\n * base64 `bytes`; `bedrock-converse` takes the event's single key as the\n * frame's event type and its value as the payload.\n *\n * The framing functions are pure. `serveRawResponse` checks and journals the\n * fixture. It writes one reply itself: the untimed 500 for a fixture that\n * fails a check, targets another wire or has no body for the request mode.\n * Every other reply goes through the shared delivery layer (`deliverStream`,\n * `deliverJson`), which owns the delay loop, writability checks and abort\n * handling. A reply with a status of 400 or more is never delayed.\n */\nimport type * as http from \"node:http\";\nimport { encodeEventStreamMessage, eventStreamCodec } from \"../aws-event-stream.js\";\nimport { rawFixtureContext } from \"../fixture-loader.js\";\nimport { flattenHeaders } from \"../helpers.js\";\nimport type { Journal } from \"../journal.js\";\nimport { recordMisbehaviorOutcome, type MisbehaviorSummary } from \"../misbehavior.js\";\nimport { serializeOpenRouterError } from \"../openrouter-chat.js\";\nimport { ndjsonCodec } from \"../ndjson-writer.js\";\nimport { checkRawResponse } from \"../raw-validation.js\";\nimport { sseCodec, writeErrorResponse } from \"../sse-writer.js\";\nimport type { Fixture, HandlerDefaults, JournalEntry, RawResponse, RawWireId } from \"../types.js\";\nimport { deliverJson, deliverStream } from \"./deliver.js\";\nimport { renderError } from \"./errors.js\";\nimport type { FrameCodec } from \"./frame-loop.js\";\nimport type { ErrorWire } from \"./profiles.js\";\n\n/** The streaming Content-Type each wire's typed handler sends. */\nexport function rawContentType(wire: RawWireId): string {\n switch (wire) {\n case \"openai-responses\":\n case \"openai-chat\":\n case \"anthropic\":\n case \"gemini\":\n case \"gemini-interactions\":\n case \"cohere\":\n return \"text/event-stream\";\n case \"ollama\":\n case \"ollama-generate\":\n return \"application/x-ndjson\";\n case \"bedrock-invoke\":\n case \"bedrock-converse\":\n return \"application/vnd.amazon.eventstream\";\n }\n}\n\n/**\n * The default headers of the typed stream on `wire`, read from the typed\n * codec: SSE and NDJSON add `Cache-Control: no-cache` and\n * `Connection: keep-alive`, the AWS event stream `Transfer-Encoding: chunked`.\n */\nfunction rawStreamHeaders(wire: RawWireId): Record<string, string> {\n switch (wire) {\n case \"openai-responses\":\n case \"openai-chat\":\n case \"anthropic\":\n case \"gemini\":\n case \"gemini-interactions\":\n case \"cohere\":\n return sseCodec({ done: false }).headers;\n case \"ollama\":\n case \"ollama-generate\":\n return ndjsonCodec().headers;\n case \"bedrock-invoke\":\n case \"bedrock-converse\":\n return eventStreamCodec().headers;\n }\n}\n\n/** The non-streaming JSON default, as `deliverJson` sends it. */\nconst JSON_HEADERS: Readonly<Record<string, string>> = { \"Content-Type\": \"application/json\" };\n\n/**\n * `defaults` with each `authored` header laid over it. Header names are\n * case-insensitive: an authored header replaces the default of the same name\n * in any letter case and takes the default's spelling, so a later spread over\n * the same defaults (as `deliverJson` does) still has one key per name.\n */\nfunction overrideHeaders(\n defaults: Readonly<Record<string, string>>,\n authored: Readonly<Record<string, string>> | undefined,\n): Record<string, string> {\n const merged: Record<string, string> = { ...defaults };\n const spelling = new Map(Object.keys(defaults).map((name) => [name.toLowerCase(), name]));\n for (const [name, value] of Object.entries(authored ?? {})) {\n merged[spelling.get(name.toLowerCase()) ?? name] = value;\n }\n return merged;\n}\n\n/** One raw event, framed for `wire`. Events are checked before framing (raw-validation.ts). */\nexport function encodeRawFrame(wire: RawWireId, event: Record<string, unknown>): string | Buffer {\n const json = JSON.stringify(event);\n switch (wire) {\n case \"openai-responses\":\n case \"anthropic\":\n case \"cohere\":\n return `event: ${String(event.type)}\\ndata: ${json}\\n\\n`;\n case \"openai-chat\":\n case \"gemini\":\n case \"gemini-interactions\":\n return `data: ${json}\\n\\n`;\n case \"ollama\":\n case \"ollama-generate\":\n return `${json}\\n`;\n case \"bedrock-invoke\":\n return encodeEventStreamMessage(\"chunk\", {\n bytes: Buffer.from(json, \"utf8\").toString(\"base64\"),\n });\n case \"bedrock-converse\": {\n // The checker guarantees exactly one key whose value is a JSON object.\n const [eventType] = Object.keys(event);\n const payload = event[eventType];\n if (payload === null || typeof payload !== \"object\" || Array.isArray(payload)) {\n throw new Error(\n `raw framing internal error: bedrock-converse event \"${eventType}\" has no object payload`,\n );\n }\n return encodeEventStreamMessage(eventType, payload);\n }\n }\n}\n\n/**\n * Bytes written after the last frame, if any. Only `openai-chat` has a\n * terminal (`data: [DONE]`), sent unless `raw.done === false` and never after\n * an interrupted stream.\n */\nexport function rawTrailer(\n wire: RawWireId,\n raw: RawResponse[\"raw\"],\n aborted: boolean,\n): string | undefined {\n if (wire === \"openai-chat\" && !aborted && raw.done !== false) return \"data: [DONE]\\n\\n\";\n return undefined;\n}\n\n// ─── Serving ──────────────────────────────────────────────────────────────────\n\n/** The error code for a request the raw fixture has no body for. */\nexport const RAW_MODE_UNAVAILABLE = \"aimock_raw_mode_unavailable\";\n/** The error code for a raw fixture that fails its checks or targets another wire. */\nexport const RAW_FIXTURE_INVALID = \"aimock_raw_fixture_invalid\";\n\n/** Everything {@link serveRawResponse} needs from the calling handler. */\nexport interface RawServeContext {\n wire: RawWireId;\n /** Whether the request asked for a stream, as the handler decides it. */\n stream: boolean;\n req: http.IncomingMessage;\n res: http.ServerResponse;\n fixture: Fixture;\n response: RawResponse;\n /** The journaled request body, as the handler journals it. */\n body: JournalEntry[\"body\"];\n journal: Journal;\n defaults: HandlerDefaults;\n testId: string;\n misbehaviorSummary?: MisbehaviorSummary;\n /** The dialect of the handler's own `renderError(…, \"misbehavior\", …)` call. */\n errorWire: ErrorWire;\n /** OpenAI chat requests that arrived on the OpenRouter route. */\n openRouter?: boolean;\n}\n\n/**\n * The raw events as a frame codec for the shared frame loop. Its headers are\n * the typed stream's defaults for `wire` with `raw.headers` laid over them.\n */\nexport function rawCodec(\n wire: RawWireId,\n raw: RawResponse[\"raw\"],\n): FrameCodec<Record<string, unknown>> {\n return {\n headers: overrideHeaders(rawStreamHeaders(wire), raw.headers),\n encode: (event) => encodeRawFrame(wire, event),\n trailer: (aborted) => {\n const trailer = rawTrailer(wire, raw, aborted);\n return trailer === undefined ? [] : [trailer];\n },\n };\n}\n\n/**\n * The error body for a raw 500, in the dialect of the handler's misbehavior\n * errors. Dialects with no code slot (Gemini, Ollama, OpenRouter) carry the\n * code as a message prefix.\n */\nfunction renderRawError(\n ctx: RawServeContext,\n code: string,\n message: string,\n): { body: string; headers?: Record<string, string> } {\n if (ctx.openRouter) return { body: serializeOpenRouterError(500, `${code}: ${message}`) };\n switch (ctx.errorWire) {\n case \"openai\":\n return renderError(\"openai\", \"misbehavior\", {\n message,\n type: \"server_error\",\n ...(ctx.wire === \"openai-chat\" ? { param: null, includeParam: true as const } : {}),\n code,\n });\n case \"messages\":\n return renderError(\"messages\", \"misbehavior\", { type: \"api_error\", code, message });\n case \"gemini\":\n return renderError(\"gemini\", \"misbehavior\", {\n bodyCode: 500,\n message: `${code}: ${message}`,\n status: \"INTERNAL\",\n });\n case \"bedrock\":\n case \"bedrock-converse\":\n return renderError(ctx.errorWire, \"misbehavior\", {\n type: \"InternalServerException\",\n code,\n message,\n });\n default:\n return renderError(ctx.errorWire, \"misbehavior\", { code, message });\n }\n}\n\n/**\n * Serve a raw passthrough fixture on the handler's wire: check it, journal it,\n * and send its events or JSON through the shared delivery layer. A fixture\n * that fails a check, targets another wire, or has no body for the requested\n * mode gets a 500 in the handler's misbehavior error dialect, and an error log\n * line. A reply with status 400 or more is never delayed, streaming or not,\n * and one with `json` answers in JSON even to a streaming request.\n */\nexport async function serveRawResponse(ctx: RawServeContext): Promise<void> {\n const { wire, stream, req, res, fixture, journal, defaults, testId } = ctx;\n const raw = ctx.response.raw;\n const journalBase = {\n method: req.method ?? \"POST\",\n path: req.url ?? \"/\",\n headers: flattenHeaders(req.headers),\n body: ctx.body,\n };\n const record = (entry: JournalEntry): void =>\n recordMisbehaviorOutcome({ entry, summary: ctx.misbehaviorSummary, defaults, testId });\n\n const status = raw.status ?? 200;\n // An error reply (status >= 400) is never delayed, streaming or not, as\n // typed error replies are not. Fixture interruptions still apply.\n const errorReply = status >= 400;\n // An error status with a JSON body answers in JSON even to a streaming\n // request, as provider APIs do; the JSON wins over any events.\n const servesStream = stream && !(errorReply && raw.json !== undefined);\n\n let failure: { code: string; message: string } | undefined;\n const problems = checkRawResponse(raw, rawFixtureContext(fixture, ctx.response)).filter(\n (finding) => finding.severity === \"error\",\n );\n if (problems.length > 0) {\n failure = {\n code: RAW_FIXTURE_INVALID,\n message: `invalid raw fixture: ${problems.map((p) => p.message).join(\"; \")}`,\n };\n } else if (raw.wire !== wire) {\n failure = { code: RAW_FIXTURE_INVALID, message: `raw fixture is for ${raw.wire}, not ${wire}` };\n } else if (servesStream ? raw.events === undefined : raw.json === undefined) {\n failure = {\n code: RAW_MODE_UNAVAILABLE,\n message: `raw fixture has no \"${servesStream ? \"events\" : \"json\"}\" body for a ${\n servesStream ? \"streaming\" : \"non-streaming\"\n } request on ${wire}`,\n };\n }\n if (failure) {\n defaults.logger.error(`${journalBase.method} ${journalBase.path}: ${failure.message}`);\n const entry = journal.add({ ...journalBase, response: { status: 500, fixture } });\n entry.response.error = failure.message;\n record(entry);\n const rendered = renderRawError(ctx, failure.code, failure.message);\n for (const [name, value] of Object.entries(rendered.headers ?? {})) res.setHeader(name, value);\n writeErrorResponse(res, 500, rendered.body);\n return;\n }\n\n const entry = journal.add({ ...journalBase, response: { status, fixture } });\n record(entry);\n\n if (servesStream) {\n const events = raw.events;\n if (events === undefined) {\n throw new Error(`raw serve internal error: a streamed reply on ${wire} has no events`);\n }\n await deliverStream(\n res,\n entry,\n fixture,\n rawCodec(wire, raw),\n events,\n errorReply\n ? { latency: 0 }\n : {\n latency: fixture.latency ?? defaults.latency,\n streamingProfile: fixture.streamingProfile,\n recordedTimings: fixture.recordedTimings,\n replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed,\n },\n // The codec already carries raw.headers over its defaults.\n { status: raw.status },\n );\n return;\n }\n\n // The wait is sized from the served JSON, as typed replies size theirs from\n // the served content, in chunks of the fixture's or server's chunk size.\n const json = raw.json;\n if (json === undefined) {\n throw new Error(`raw serve internal error: a JSON reply on ${wire} has no json`);\n }\n const servedLength = JSON.stringify(json).length;\n // deliverJson reads the timing opt-ins from the fixture. With them off, an\n // error reply still gets its writability check and journaling, but no wait.\n await deliverJson(\n res,\n entry,\n errorReply\n ? { ...fixture, nonStreamingTiming: false, nonStreamingTimingAllProviders: false }\n : fixture,\n () => json,\n {\n surface: wire === \"openai-chat\" ? \"openai-chat\" : \"other\",\n status: raw.status,\n payloadLength: servedLength,\n chunkSize: Math.max(1, fixture.chunkSize ?? defaults.chunkSize),\n recordedTimings: fixture.recordedTimings,\n replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed,\n headers: overrideHeaders(JSON_HEADERS, raw.headers),\n },\n );\n}\n"],"mappings":"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"}