@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,177 @@
1
+ const require_runtime = require('./_virtual/_rolldown/runtime.cjs');
2
+ let node_http = require("node:http");
3
+
4
+ //#region src/raw-validation.ts
5
+ /**
6
+ * @internal Shape checks for raw passthrough responses (#549). One pure
7
+ * checker serves load-time validation (`validateFixtures`) and the serve-time
8
+ * check, which runs on every raw fixture served (including factories and
9
+ * `on()` fixtures, which skip load validation). Not exported from the package
10
+ * entry point.
11
+ */
12
+ /** Every {@link RawWireId}; the `satisfies` + exhaustiveness check keep it in sync. */
13
+ const RAW_WIRE_IDS = [
14
+ "openai-responses",
15
+ "openai-chat",
16
+ "anthropic",
17
+ "gemini",
18
+ "gemini-interactions",
19
+ "cohere",
20
+ "ollama",
21
+ "ollama-generate",
22
+ "bedrock-invoke",
23
+ "bedrock-converse"
24
+ ];
25
+ function isRawWireId(value) {
26
+ return typeof value === "string" && RAW_WIRE_IDS.includes(value);
27
+ }
28
+ /** Headers that break or misdescribe a body aimock frames itself. */
29
+ const FORBIDDEN_HEADERS = new Set([
30
+ "content-length",
31
+ "transfer-encoding",
32
+ "connection",
33
+ "content-encoding"
34
+ ]);
35
+ /** Wires whose framing takes the SSE event name from the event's string `type`. */
36
+ const TYPE_NAMED_WIRES = new Set([
37
+ "openai-responses",
38
+ "anthropic",
39
+ "cohere"
40
+ ]);
41
+ /** The fields of `raw`; any other key is reported as ignored. */
42
+ const RAW_FIELDS = [
43
+ "wire",
44
+ "events",
45
+ "json",
46
+ "status",
47
+ "headers",
48
+ "done"
49
+ ];
50
+ /** Statuses whose replies carry no body: Node drops anything written for them. */
51
+ const BODYLESS_STATUSES = new Set([204, 304]);
52
+ /**
53
+ * The longest AWS event-stream header value, in bytes. The encoder writes the
54
+ * length as a uint16 (aws-event-stream.ts), so it cannot frame a longer one.
55
+ */
56
+ const EVENT_STREAM_HEADER_VALUE_MAX_BYTES = 65535;
57
+ /** A plain object, as JSON.parse makes one: not an array, Date, Map or class instance. */
58
+ function isPlainObject(value) {
59
+ if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
60
+ const proto = Object.getPrototypeOf(value);
61
+ return proto === Object.prototype || proto === null;
62
+ }
63
+ /**
64
+ * The first part of `value` that JSON.parse cannot produce (a sparse-array
65
+ * hole, `undefined`, a non-finite number, a function, a Date or other
66
+ * non-plain object, a cycle), as `[path, problem]`. Undefined for plain JSON.
67
+ */
68
+ function jsonProblem(value, path, ancestors = []) {
69
+ if (value === null || typeof value === "string" || typeof value === "boolean") return void 0;
70
+ if (typeof value === "number") return Number.isFinite(value) ? void 0 : [path, "must be a finite number"];
71
+ if (typeof value !== "object") return [path, `must be a JSON value; got ${typeof value}`];
72
+ if (ancestors.includes(value)) return [path, "must not contain itself"];
73
+ const inner = [...ancestors, value];
74
+ if (Array.isArray(value)) {
75
+ for (let i = 0; i < value.length; i++) {
76
+ if (!(i in value)) return [`${path}[${i}]`, "must not be a hole in a sparse array"];
77
+ const problem = jsonProblem(value[i], `${path}[${i}]`, inner);
78
+ if (problem) return problem;
79
+ }
80
+ return;
81
+ }
82
+ if (!isPlainObject(value)) return [path, "must be a plain JSON object"];
83
+ for (const [key, item] of Object.entries(value)) {
84
+ const problem = jsonProblem(item, `${path}[${JSON.stringify(key)}]`, inner);
85
+ if (problem) return problem;
86
+ }
87
+ }
88
+ /**
89
+ * Check a raw response's `raw` value and the fixture facts in `context`.
90
+ * Returns every finding. The fixture is servable when no finding has severity
91
+ * `"error"`: an empty array or one with only warnings. Pure: no logging, no
92
+ * throwing. Load validation and serve time both call it, so they agree on
93
+ * what a valid raw fixture is.
94
+ */
95
+ function checkRawResponse(raw, context = {}) {
96
+ const findings = [];
97
+ const error = (message) => findings.push({
98
+ severity: "error",
99
+ message
100
+ });
101
+ for (const key of context.otherResponseKeys ?? []) error(`raw cannot be combined with ${JSON.stringify(key)}: a raw fixture has no other response type`);
102
+ if (context.fixtureMisbehavior) error("misbehavior does not apply to raw fixtures");
103
+ if (!isPlainObject(raw)) {
104
+ error("raw must be an object");
105
+ return findings;
106
+ }
107
+ for (const key of Object.keys(raw)) if (!RAW_FIELDS.includes(key)) findings.push({
108
+ severity: "warning",
109
+ message: `raw[${JSON.stringify(key)}] is ignored: not a raw field (${RAW_FIELDS.join(", ")})`
110
+ });
111
+ const wire = isRawWireId(raw.wire) ? raw.wire : void 0;
112
+ if (wire === void 0) error(`raw.wire must be one of ${RAW_WIRE_IDS.join(", ")}; got ${JSON.stringify(raw.wire)}`);
113
+ const events = raw.events;
114
+ if (events === void 0 && raw.json === void 0) error("raw needs \"events\" (streaming), \"json\" (non-streaming), or both");
115
+ if (events !== void 0) if (!Array.isArray(events)) error("raw.events must be an array");
116
+ else {
117
+ if (events.length === 0) findings.push({
118
+ severity: "warning",
119
+ message: "raw.events is empty; a streaming request gets no frames"
120
+ });
121
+ for (let i = 0; i < events.length; i++) {
122
+ const event = events[i];
123
+ if (!isPlainObject(event)) {
124
+ error(`raw.events[${i}] must be a JSON object`);
125
+ continue;
126
+ }
127
+ const problem = jsonProblem(event, `raw.events[${i}]`);
128
+ if (problem) {
129
+ error(`${problem[0]} ${problem[1]}`);
130
+ continue;
131
+ }
132
+ if (wire !== void 0 && TYPE_NAMED_WIRES.has(wire)) {
133
+ if (typeof event.type !== "string") error(`raw.events[${i}] needs a string "type" on ${wire}`);
134
+ else if (/[\r\n]/.test(event.type)) error(`raw.events[${i}].type must not contain a line break (CR or LF) on ${wire}`);
135
+ }
136
+ if (wire === "bedrock-converse") {
137
+ const keys = Object.keys(event);
138
+ if (keys.length !== 1) error(`raw.events[${i}] must have exactly one top-level key (the event type) on bedrock-converse`);
139
+ else if (Buffer.byteLength(keys[0], "utf8") > EVENT_STREAM_HEADER_VALUE_MAX_BYTES) error(`raw.events[${i}] has an event type key over ${EVENT_STREAM_HEADER_VALUE_MAX_BYTES} bytes, the event-stream header limit, on bedrock-converse`);
140
+ else if (!isPlainObject(event[keys[0]])) error(`raw.events[${i}].${keys[0]} must be a JSON object (the frame payload) on bedrock-converse`);
141
+ }
142
+ }
143
+ }
144
+ if (raw.status !== void 0) {
145
+ const status = raw.status;
146
+ if (typeof status !== "number" || !Number.isInteger(status) || status < 200 || status > 599) error(`raw.status must be an integer from 200 to 599; got ${JSON.stringify(status)}`);
147
+ else if (BODYLESS_STATUSES.has(status)) error(`raw.status ${status} cannot carry a body, so "events" and "json" would be dropped; use a status that allows a body`);
148
+ }
149
+ if (raw.headers !== void 0) if (!isPlainObject(raw.headers)) error("raw.headers must be an object of string values");
150
+ else for (const [name, value] of Object.entries(raw.headers)) {
151
+ const label = `raw.headers[${JSON.stringify(name)}]`;
152
+ if (typeof value !== "string") {
153
+ error(`${label} must be a string`);
154
+ continue;
155
+ }
156
+ try {
157
+ (0, node_http.validateHeaderName)(name);
158
+ } catch {
159
+ error(`${label} is not a valid header name`);
160
+ continue;
161
+ }
162
+ try {
163
+ (0, node_http.validateHeaderValue)(name, value);
164
+ } catch {
165
+ error(`${label} has an invalid header value`);
166
+ continue;
167
+ }
168
+ if (FORBIDDEN_HEADERS.has(name.toLowerCase())) error(`${label} is not allowed: aimock frames the body and sets this header itself`);
169
+ }
170
+ if (raw.done !== void 0 && typeof raw.done !== "boolean") error(`raw.done must be a boolean; got ${JSON.stringify(raw.done)}`);
171
+ else if (raw.done !== void 0 && wire !== void 0 && wire !== "openai-chat") error(`raw.done applies only to openai-chat (the only wire with a [DONE] terminal), not ${wire}`);
172
+ return findings;
173
+ }
174
+
175
+ //#endregion
176
+ exports.checkRawResponse = checkRawResponse;
177
+ //# sourceMappingURL=raw-validation.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"raw-validation.cjs","names":[],"sources":["../src/raw-validation.ts"],"sourcesContent":["/**\n * @internal Shape checks for raw passthrough responses (#549). One pure\n * checker serves load-time validation (`validateFixtures`) and the serve-time\n * check, which runs on every raw fixture served (including factories and\n * `on()` fixtures, which skip load validation). Not exported from the package\n * entry point.\n */\nimport { validateHeaderName, validateHeaderValue } from \"node:http\";\nimport type { RawResponse, RawWireId } from \"./types.js\";\n\nexport interface RawFinding {\n severity: \"error\" | \"warning\";\n message: string;\n}\n\n/** Every {@link RawWireId}; the `satisfies` + exhaustiveness check keep it in sync. */\nexport const RAW_WIRE_IDS = [\n \"openai-responses\",\n \"openai-chat\",\n \"anthropic\",\n \"gemini\",\n \"gemini-interactions\",\n \"cohere\",\n \"ollama\",\n \"ollama-generate\",\n \"bedrock-invoke\",\n \"bedrock-converse\",\n] as const satisfies readonly RawWireId[];\n\n// Compile-time: fails if RawWireId gains a member RAW_WIRE_IDS lacks.\ntype MissingRawWire = Exclude<RawWireId, (typeof RAW_WIRE_IDS)[number]>;\nconst rawWireIdsComplete: MissingRawWire extends never ? true : never = true;\nvoid rawWireIdsComplete;\n\nexport function isRawWireId(value: unknown): value is RawWireId {\n return typeof value === \"string\" && (RAW_WIRE_IDS as readonly string[]).includes(value);\n}\n\n/** Headers that break or misdescribe a body aimock frames itself. */\nconst FORBIDDEN_HEADERS = new Set([\n \"content-length\",\n \"transfer-encoding\",\n \"connection\",\n \"content-encoding\",\n]);\n\n/** Wires whose framing takes the SSE event name from the event's string `type`. */\nconst TYPE_NAMED_WIRES: ReadonlySet<RawWireId> = new Set([\n \"openai-responses\",\n \"anthropic\",\n \"cohere\",\n]);\n\n/** The fields of `raw`; any other key is reported as ignored. */\nconst RAW_FIELDS: readonly string[] = [\n \"wire\",\n \"events\",\n \"json\",\n \"status\",\n \"headers\",\n \"done\",\n] satisfies (keyof RawResponse[\"raw\"])[];\n\n/** Statuses whose replies carry no body: Node drops anything written for them. */\nconst BODYLESS_STATUSES: ReadonlySet<number> = new Set([204, 304]);\n\n/**\n * The longest AWS event-stream header value, in bytes. The encoder writes the\n * length as a uint16 (aws-event-stream.ts), so it cannot frame a longer one.\n */\nconst EVENT_STREAM_HEADER_VALUE_MAX_BYTES = 0xffff;\n\n/** A plain object, as JSON.parse makes one: not an array, Date, Map or class instance. */\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) return false;\n const proto: unknown = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\n/**\n * The first part of `value` that JSON.parse cannot produce (a sparse-array\n * hole, `undefined`, a non-finite number, a function, a Date or other\n * non-plain object, a cycle), as `[path, problem]`. Undefined for plain JSON.\n */\nfunction jsonProblem(\n value: unknown,\n path: string,\n ancestors: readonly object[] = [],\n): [string, string] | undefined {\n if (value === null || typeof value === \"string\" || typeof value === \"boolean\") return undefined;\n if (typeof value === \"number\") {\n return Number.isFinite(value) ? undefined : [path, \"must be a finite number\"];\n }\n if (typeof value !== \"object\") return [path, `must be a JSON value; got ${typeof value}`];\n if (ancestors.includes(value)) return [path, \"must not contain itself\"];\n const inner = [...ancestors, value];\n if (Array.isArray(value)) {\n for (let i = 0; i < value.length; i++) {\n if (!(i in value)) return [`${path}[${i}]`, \"must not be a hole in a sparse array\"];\n const problem = jsonProblem(value[i], `${path}[${i}]`, inner);\n if (problem) return problem;\n }\n return undefined;\n }\n if (!isPlainObject(value)) return [path, \"must be a plain JSON object\"];\n for (const [key, item] of Object.entries(value)) {\n const problem = jsonProblem(item, `${path}[${JSON.stringify(key)}]`, inner);\n if (problem) return problem;\n }\n return undefined;\n}\n\n/** What the caller knows about the fixture around `raw`. */\nexport interface RawCheckContext {\n /**\n * Response-type keys written next to `raw`, such as `customToolCalls` or\n * `responsesBlocks` (a legacy server drops these two before serving).\n */\n otherResponseKeys?: readonly string[];\n /** Whether the fixture sets its own `misbehavior`. */\n fixtureMisbehavior?: boolean;\n}\n\n/**\n * Check a raw response's `raw` value and the fixture facts in `context`.\n * Returns every finding. The fixture is servable when no finding has severity\n * `\"error\"`: an empty array or one with only warnings. Pure: no logging, no\n * throwing. Load validation and serve time both call it, so they agree on\n * what a valid raw fixture is.\n */\nexport function checkRawResponse(raw: unknown, context: RawCheckContext = {}): RawFinding[] {\n const findings: RawFinding[] = [];\n const error = (message: string) => findings.push({ severity: \"error\", message });\n\n for (const key of context.otherResponseKeys ?? []) {\n error(\n `raw cannot be combined with ${JSON.stringify(key)}: a raw fixture has no other response type`,\n );\n }\n if (context.fixtureMisbehavior) {\n error(\"misbehavior does not apply to raw fixtures\");\n }\n\n if (!isPlainObject(raw)) {\n error(\"raw must be an object\");\n return findings;\n }\n\n for (const key of Object.keys(raw)) {\n if (!RAW_FIELDS.includes(key)) {\n findings.push({\n severity: \"warning\",\n message: `raw[${JSON.stringify(key)}] is ignored: not a raw field (${RAW_FIELDS.join(\", \")})`,\n });\n }\n }\n\n const wire = isRawWireId(raw.wire) ? raw.wire : undefined;\n if (wire === undefined) {\n error(`raw.wire must be one of ${RAW_WIRE_IDS.join(\", \")}; got ${JSON.stringify(raw.wire)}`);\n }\n\n const events = raw.events;\n if (events === undefined && raw.json === undefined) {\n error('raw needs \"events\" (streaming), \"json\" (non-streaming), or both');\n }\n if (events !== undefined) {\n if (!Array.isArray(events)) {\n error(\"raw.events must be an array\");\n } else {\n if (events.length === 0) {\n findings.push({\n severity: \"warning\",\n message: \"raw.events is empty; a streaming request gets no frames\",\n });\n }\n // An index loop, not forEach: forEach skips the holes of a sparse array.\n for (let i = 0; i < events.length; i++) {\n const event: unknown = events[i];\n if (!isPlainObject(event)) {\n error(`raw.events[${i}] must be a JSON object`);\n continue;\n }\n const problem = jsonProblem(event, `raw.events[${i}]`);\n if (problem) {\n error(`${problem[0]} ${problem[1]}`);\n continue;\n }\n if (wire !== undefined && TYPE_NAMED_WIRES.has(wire)) {\n if (typeof event.type !== \"string\") {\n error(`raw.events[${i}] needs a string \"type\" on ${wire}`);\n } else if (/[\\r\\n]/.test(event.type)) {\n // The type is written as the SSE `event:` line; a line break\n // would start another SSE field or frame.\n error(`raw.events[${i}].type must not contain a line break (CR or LF) on ${wire}`);\n }\n }\n if (wire === \"bedrock-converse\") {\n const keys = Object.keys(event);\n if (keys.length !== 1) {\n error(\n `raw.events[${i}] must have exactly one top-level key (the event type) on bedrock-converse`,\n );\n } else if (Buffer.byteLength(keys[0], \"utf8\") > EVENT_STREAM_HEADER_VALUE_MAX_BYTES) {\n error(\n `raw.events[${i}] has an event type key over ${EVENT_STREAM_HEADER_VALUE_MAX_BYTES} bytes, the event-stream header limit, on bedrock-converse`,\n );\n } else if (!isPlainObject(event[keys[0]])) {\n error(\n `raw.events[${i}].${keys[0]} must be a JSON object (the frame payload) on bedrock-converse`,\n );\n }\n }\n }\n }\n }\n\n if (raw.status !== undefined) {\n const status = raw.status;\n if (typeof status !== \"number\" || !Number.isInteger(status) || status < 200 || status > 599) {\n error(`raw.status must be an integer from 200 to 599; got ${JSON.stringify(status)}`);\n } else if (BODYLESS_STATUSES.has(status)) {\n error(\n `raw.status ${status} cannot carry a body, so \"events\" and \"json\" would be dropped; use a status that allows a body`,\n );\n }\n }\n\n if (raw.headers !== undefined) {\n if (!isPlainObject(raw.headers)) {\n error(\"raw.headers must be an object of string values\");\n } else {\n for (const [name, value] of Object.entries(raw.headers)) {\n const label = `raw.headers[${JSON.stringify(name)}]`;\n if (typeof value !== \"string\") {\n error(`${label} must be a string`);\n continue;\n }\n try {\n validateHeaderName(name);\n } catch {\n error(`${label} is not a valid header name`);\n continue;\n }\n try {\n validateHeaderValue(name, value);\n } catch {\n error(`${label} has an invalid header value`);\n continue;\n }\n if (FORBIDDEN_HEADERS.has(name.toLowerCase())) {\n error(`${label} is not allowed: aimock frames the body and sets this header itself`);\n }\n }\n }\n }\n\n if (raw.done !== undefined && typeof raw.done !== \"boolean\") {\n error(`raw.done must be a boolean; got ${JSON.stringify(raw.done)}`);\n } else if (raw.done !== undefined && wire !== undefined && wire !== \"openai-chat\") {\n error(\n `raw.done applies only to openai-chat (the only wire with a [DONE] terminal), not ${wire}`,\n );\n }\n\n return findings;\n}\n"],"mappings":"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"}
@@ -0,0 +1,176 @@
1
+ import { validateHeaderName, validateHeaderValue } from "node:http";
2
+
3
+ //#region src/raw-validation.ts
4
+ /**
5
+ * @internal Shape checks for raw passthrough responses (#549). One pure
6
+ * checker serves load-time validation (`validateFixtures`) and the serve-time
7
+ * check, which runs on every raw fixture served (including factories and
8
+ * `on()` fixtures, which skip load validation). Not exported from the package
9
+ * entry point.
10
+ */
11
+ /** Every {@link RawWireId}; the `satisfies` + exhaustiveness check keep it in sync. */
12
+ const RAW_WIRE_IDS = [
13
+ "openai-responses",
14
+ "openai-chat",
15
+ "anthropic",
16
+ "gemini",
17
+ "gemini-interactions",
18
+ "cohere",
19
+ "ollama",
20
+ "ollama-generate",
21
+ "bedrock-invoke",
22
+ "bedrock-converse"
23
+ ];
24
+ function isRawWireId(value) {
25
+ return typeof value === "string" && RAW_WIRE_IDS.includes(value);
26
+ }
27
+ /** Headers that break or misdescribe a body aimock frames itself. */
28
+ const FORBIDDEN_HEADERS = new Set([
29
+ "content-length",
30
+ "transfer-encoding",
31
+ "connection",
32
+ "content-encoding"
33
+ ]);
34
+ /** Wires whose framing takes the SSE event name from the event's string `type`. */
35
+ const TYPE_NAMED_WIRES = new Set([
36
+ "openai-responses",
37
+ "anthropic",
38
+ "cohere"
39
+ ]);
40
+ /** The fields of `raw`; any other key is reported as ignored. */
41
+ const RAW_FIELDS = [
42
+ "wire",
43
+ "events",
44
+ "json",
45
+ "status",
46
+ "headers",
47
+ "done"
48
+ ];
49
+ /** Statuses whose replies carry no body: Node drops anything written for them. */
50
+ const BODYLESS_STATUSES = new Set([204, 304]);
51
+ /**
52
+ * The longest AWS event-stream header value, in bytes. The encoder writes the
53
+ * length as a uint16 (aws-event-stream.ts), so it cannot frame a longer one.
54
+ */
55
+ const EVENT_STREAM_HEADER_VALUE_MAX_BYTES = 65535;
56
+ /** A plain object, as JSON.parse makes one: not an array, Date, Map or class instance. */
57
+ function isPlainObject(value) {
58
+ if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
59
+ const proto = Object.getPrototypeOf(value);
60
+ return proto === Object.prototype || proto === null;
61
+ }
62
+ /**
63
+ * The first part of `value` that JSON.parse cannot produce (a sparse-array
64
+ * hole, `undefined`, a non-finite number, a function, a Date or other
65
+ * non-plain object, a cycle), as `[path, problem]`. Undefined for plain JSON.
66
+ */
67
+ function jsonProblem(value, path, ancestors = []) {
68
+ if (value === null || typeof value === "string" || typeof value === "boolean") return void 0;
69
+ if (typeof value === "number") return Number.isFinite(value) ? void 0 : [path, "must be a finite number"];
70
+ if (typeof value !== "object") return [path, `must be a JSON value; got ${typeof value}`];
71
+ if (ancestors.includes(value)) return [path, "must not contain itself"];
72
+ const inner = [...ancestors, value];
73
+ if (Array.isArray(value)) {
74
+ for (let i = 0; i < value.length; i++) {
75
+ if (!(i in value)) return [`${path}[${i}]`, "must not be a hole in a sparse array"];
76
+ const problem = jsonProblem(value[i], `${path}[${i}]`, inner);
77
+ if (problem) return problem;
78
+ }
79
+ return;
80
+ }
81
+ if (!isPlainObject(value)) return [path, "must be a plain JSON object"];
82
+ for (const [key, item] of Object.entries(value)) {
83
+ const problem = jsonProblem(item, `${path}[${JSON.stringify(key)}]`, inner);
84
+ if (problem) return problem;
85
+ }
86
+ }
87
+ /**
88
+ * Check a raw response's `raw` value and the fixture facts in `context`.
89
+ * Returns every finding. The fixture is servable when no finding has severity
90
+ * `"error"`: an empty array or one with only warnings. Pure: no logging, no
91
+ * throwing. Load validation and serve time both call it, so they agree on
92
+ * what a valid raw fixture is.
93
+ */
94
+ function checkRawResponse(raw, context = {}) {
95
+ const findings = [];
96
+ const error = (message) => findings.push({
97
+ severity: "error",
98
+ message
99
+ });
100
+ for (const key of context.otherResponseKeys ?? []) error(`raw cannot be combined with ${JSON.stringify(key)}: a raw fixture has no other response type`);
101
+ if (context.fixtureMisbehavior) error("misbehavior does not apply to raw fixtures");
102
+ if (!isPlainObject(raw)) {
103
+ error("raw must be an object");
104
+ return findings;
105
+ }
106
+ for (const key of Object.keys(raw)) if (!RAW_FIELDS.includes(key)) findings.push({
107
+ severity: "warning",
108
+ message: `raw[${JSON.stringify(key)}] is ignored: not a raw field (${RAW_FIELDS.join(", ")})`
109
+ });
110
+ const wire = isRawWireId(raw.wire) ? raw.wire : void 0;
111
+ if (wire === void 0) error(`raw.wire must be one of ${RAW_WIRE_IDS.join(", ")}; got ${JSON.stringify(raw.wire)}`);
112
+ const events = raw.events;
113
+ if (events === void 0 && raw.json === void 0) error("raw needs \"events\" (streaming), \"json\" (non-streaming), or both");
114
+ if (events !== void 0) if (!Array.isArray(events)) error("raw.events must be an array");
115
+ else {
116
+ if (events.length === 0) findings.push({
117
+ severity: "warning",
118
+ message: "raw.events is empty; a streaming request gets no frames"
119
+ });
120
+ for (let i = 0; i < events.length; i++) {
121
+ const event = events[i];
122
+ if (!isPlainObject(event)) {
123
+ error(`raw.events[${i}] must be a JSON object`);
124
+ continue;
125
+ }
126
+ const problem = jsonProblem(event, `raw.events[${i}]`);
127
+ if (problem) {
128
+ error(`${problem[0]} ${problem[1]}`);
129
+ continue;
130
+ }
131
+ if (wire !== void 0 && TYPE_NAMED_WIRES.has(wire)) {
132
+ if (typeof event.type !== "string") error(`raw.events[${i}] needs a string "type" on ${wire}`);
133
+ else if (/[\r\n]/.test(event.type)) error(`raw.events[${i}].type must not contain a line break (CR or LF) on ${wire}`);
134
+ }
135
+ if (wire === "bedrock-converse") {
136
+ const keys = Object.keys(event);
137
+ if (keys.length !== 1) error(`raw.events[${i}] must have exactly one top-level key (the event type) on bedrock-converse`);
138
+ else if (Buffer.byteLength(keys[0], "utf8") > EVENT_STREAM_HEADER_VALUE_MAX_BYTES) error(`raw.events[${i}] has an event type key over ${EVENT_STREAM_HEADER_VALUE_MAX_BYTES} bytes, the event-stream header limit, on bedrock-converse`);
139
+ else if (!isPlainObject(event[keys[0]])) error(`raw.events[${i}].${keys[0]} must be a JSON object (the frame payload) on bedrock-converse`);
140
+ }
141
+ }
142
+ }
143
+ if (raw.status !== void 0) {
144
+ const status = raw.status;
145
+ if (typeof status !== "number" || !Number.isInteger(status) || status < 200 || status > 599) error(`raw.status must be an integer from 200 to 599; got ${JSON.stringify(status)}`);
146
+ else if (BODYLESS_STATUSES.has(status)) error(`raw.status ${status} cannot carry a body, so "events" and "json" would be dropped; use a status that allows a body`);
147
+ }
148
+ if (raw.headers !== void 0) if (!isPlainObject(raw.headers)) error("raw.headers must be an object of string values");
149
+ else for (const [name, value] of Object.entries(raw.headers)) {
150
+ const label = `raw.headers[${JSON.stringify(name)}]`;
151
+ if (typeof value !== "string") {
152
+ error(`${label} must be a string`);
153
+ continue;
154
+ }
155
+ try {
156
+ validateHeaderName(name);
157
+ } catch {
158
+ error(`${label} is not a valid header name`);
159
+ continue;
160
+ }
161
+ try {
162
+ validateHeaderValue(name, value);
163
+ } catch {
164
+ error(`${label} has an invalid header value`);
165
+ continue;
166
+ }
167
+ if (FORBIDDEN_HEADERS.has(name.toLowerCase())) error(`${label} is not allowed: aimock frames the body and sets this header itself`);
168
+ }
169
+ if (raw.done !== void 0 && typeof raw.done !== "boolean") error(`raw.done must be a boolean; got ${JSON.stringify(raw.done)}`);
170
+ else if (raw.done !== void 0 && wire !== void 0 && wire !== "openai-chat") error(`raw.done applies only to openai-chat (the only wire with a [DONE] terminal), not ${wire}`);
171
+ return findings;
172
+ }
173
+
174
+ //#endregion
175
+ export { checkRawResponse };
176
+ //# sourceMappingURL=raw-validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"raw-validation.js","names":[],"sources":["../src/raw-validation.ts"],"sourcesContent":["/**\n * @internal Shape checks for raw passthrough responses (#549). One pure\n * checker serves load-time validation (`validateFixtures`) and the serve-time\n * check, which runs on every raw fixture served (including factories and\n * `on()` fixtures, which skip load validation). Not exported from the package\n * entry point.\n */\nimport { validateHeaderName, validateHeaderValue } from \"node:http\";\nimport type { RawResponse, RawWireId } from \"./types.js\";\n\nexport interface RawFinding {\n severity: \"error\" | \"warning\";\n message: string;\n}\n\n/** Every {@link RawWireId}; the `satisfies` + exhaustiveness check keep it in sync. */\nexport const RAW_WIRE_IDS = [\n \"openai-responses\",\n \"openai-chat\",\n \"anthropic\",\n \"gemini\",\n \"gemini-interactions\",\n \"cohere\",\n \"ollama\",\n \"ollama-generate\",\n \"bedrock-invoke\",\n \"bedrock-converse\",\n] as const satisfies readonly RawWireId[];\n\n// Compile-time: fails if RawWireId gains a member RAW_WIRE_IDS lacks.\ntype MissingRawWire = Exclude<RawWireId, (typeof RAW_WIRE_IDS)[number]>;\nconst rawWireIdsComplete: MissingRawWire extends never ? true : never = true;\nvoid rawWireIdsComplete;\n\nexport function isRawWireId(value: unknown): value is RawWireId {\n return typeof value === \"string\" && (RAW_WIRE_IDS as readonly string[]).includes(value);\n}\n\n/** Headers that break or misdescribe a body aimock frames itself. */\nconst FORBIDDEN_HEADERS = new Set([\n \"content-length\",\n \"transfer-encoding\",\n \"connection\",\n \"content-encoding\",\n]);\n\n/** Wires whose framing takes the SSE event name from the event's string `type`. */\nconst TYPE_NAMED_WIRES: ReadonlySet<RawWireId> = new Set([\n \"openai-responses\",\n \"anthropic\",\n \"cohere\",\n]);\n\n/** The fields of `raw`; any other key is reported as ignored. */\nconst RAW_FIELDS: readonly string[] = [\n \"wire\",\n \"events\",\n \"json\",\n \"status\",\n \"headers\",\n \"done\",\n] satisfies (keyof RawResponse[\"raw\"])[];\n\n/** Statuses whose replies carry no body: Node drops anything written for them. */\nconst BODYLESS_STATUSES: ReadonlySet<number> = new Set([204, 304]);\n\n/**\n * The longest AWS event-stream header value, in bytes. The encoder writes the\n * length as a uint16 (aws-event-stream.ts), so it cannot frame a longer one.\n */\nconst EVENT_STREAM_HEADER_VALUE_MAX_BYTES = 0xffff;\n\n/** A plain object, as JSON.parse makes one: not an array, Date, Map or class instance. */\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) return false;\n const proto: unknown = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\n/**\n * The first part of `value` that JSON.parse cannot produce (a sparse-array\n * hole, `undefined`, a non-finite number, a function, a Date or other\n * non-plain object, a cycle), as `[path, problem]`. Undefined for plain JSON.\n */\nfunction jsonProblem(\n value: unknown,\n path: string,\n ancestors: readonly object[] = [],\n): [string, string] | undefined {\n if (value === null || typeof value === \"string\" || typeof value === \"boolean\") return undefined;\n if (typeof value === \"number\") {\n return Number.isFinite(value) ? undefined : [path, \"must be a finite number\"];\n }\n if (typeof value !== \"object\") return [path, `must be a JSON value; got ${typeof value}`];\n if (ancestors.includes(value)) return [path, \"must not contain itself\"];\n const inner = [...ancestors, value];\n if (Array.isArray(value)) {\n for (let i = 0; i < value.length; i++) {\n if (!(i in value)) return [`${path}[${i}]`, \"must not be a hole in a sparse array\"];\n const problem = jsonProblem(value[i], `${path}[${i}]`, inner);\n if (problem) return problem;\n }\n return undefined;\n }\n if (!isPlainObject(value)) return [path, \"must be a plain JSON object\"];\n for (const [key, item] of Object.entries(value)) {\n const problem = jsonProblem(item, `${path}[${JSON.stringify(key)}]`, inner);\n if (problem) return problem;\n }\n return undefined;\n}\n\n/** What the caller knows about the fixture around `raw`. */\nexport interface RawCheckContext {\n /**\n * Response-type keys written next to `raw`, such as `customToolCalls` or\n * `responsesBlocks` (a legacy server drops these two before serving).\n */\n otherResponseKeys?: readonly string[];\n /** Whether the fixture sets its own `misbehavior`. */\n fixtureMisbehavior?: boolean;\n}\n\n/**\n * Check a raw response's `raw` value and the fixture facts in `context`.\n * Returns every finding. The fixture is servable when no finding has severity\n * `\"error\"`: an empty array or one with only warnings. Pure: no logging, no\n * throwing. Load validation and serve time both call it, so they agree on\n * what a valid raw fixture is.\n */\nexport function checkRawResponse(raw: unknown, context: RawCheckContext = {}): RawFinding[] {\n const findings: RawFinding[] = [];\n const error = (message: string) => findings.push({ severity: \"error\", message });\n\n for (const key of context.otherResponseKeys ?? []) {\n error(\n `raw cannot be combined with ${JSON.stringify(key)}: a raw fixture has no other response type`,\n );\n }\n if (context.fixtureMisbehavior) {\n error(\"misbehavior does not apply to raw fixtures\");\n }\n\n if (!isPlainObject(raw)) {\n error(\"raw must be an object\");\n return findings;\n }\n\n for (const key of Object.keys(raw)) {\n if (!RAW_FIELDS.includes(key)) {\n findings.push({\n severity: \"warning\",\n message: `raw[${JSON.stringify(key)}] is ignored: not a raw field (${RAW_FIELDS.join(\", \")})`,\n });\n }\n }\n\n const wire = isRawWireId(raw.wire) ? raw.wire : undefined;\n if (wire === undefined) {\n error(`raw.wire must be one of ${RAW_WIRE_IDS.join(\", \")}; got ${JSON.stringify(raw.wire)}`);\n }\n\n const events = raw.events;\n if (events === undefined && raw.json === undefined) {\n error('raw needs \"events\" (streaming), \"json\" (non-streaming), or both');\n }\n if (events !== undefined) {\n if (!Array.isArray(events)) {\n error(\"raw.events must be an array\");\n } else {\n if (events.length === 0) {\n findings.push({\n severity: \"warning\",\n message: \"raw.events is empty; a streaming request gets no frames\",\n });\n }\n // An index loop, not forEach: forEach skips the holes of a sparse array.\n for (let i = 0; i < events.length; i++) {\n const event: unknown = events[i];\n if (!isPlainObject(event)) {\n error(`raw.events[${i}] must be a JSON object`);\n continue;\n }\n const problem = jsonProblem(event, `raw.events[${i}]`);\n if (problem) {\n error(`${problem[0]} ${problem[1]}`);\n continue;\n }\n if (wire !== undefined && TYPE_NAMED_WIRES.has(wire)) {\n if (typeof event.type !== \"string\") {\n error(`raw.events[${i}] needs a string \"type\" on ${wire}`);\n } else if (/[\\r\\n]/.test(event.type)) {\n // The type is written as the SSE `event:` line; a line break\n // would start another SSE field or frame.\n error(`raw.events[${i}].type must not contain a line break (CR or LF) on ${wire}`);\n }\n }\n if (wire === \"bedrock-converse\") {\n const keys = Object.keys(event);\n if (keys.length !== 1) {\n error(\n `raw.events[${i}] must have exactly one top-level key (the event type) on bedrock-converse`,\n );\n } else if (Buffer.byteLength(keys[0], \"utf8\") > EVENT_STREAM_HEADER_VALUE_MAX_BYTES) {\n error(\n `raw.events[${i}] has an event type key over ${EVENT_STREAM_HEADER_VALUE_MAX_BYTES} bytes, the event-stream header limit, on bedrock-converse`,\n );\n } else if (!isPlainObject(event[keys[0]])) {\n error(\n `raw.events[${i}].${keys[0]} must be a JSON object (the frame payload) on bedrock-converse`,\n );\n }\n }\n }\n }\n }\n\n if (raw.status !== undefined) {\n const status = raw.status;\n if (typeof status !== \"number\" || !Number.isInteger(status) || status < 200 || status > 599) {\n error(`raw.status must be an integer from 200 to 599; got ${JSON.stringify(status)}`);\n } else if (BODYLESS_STATUSES.has(status)) {\n error(\n `raw.status ${status} cannot carry a body, so \"events\" and \"json\" would be dropped; use a status that allows a body`,\n );\n }\n }\n\n if (raw.headers !== undefined) {\n if (!isPlainObject(raw.headers)) {\n error(\"raw.headers must be an object of string values\");\n } else {\n for (const [name, value] of Object.entries(raw.headers)) {\n const label = `raw.headers[${JSON.stringify(name)}]`;\n if (typeof value !== \"string\") {\n error(`${label} must be a string`);\n continue;\n }\n try {\n validateHeaderName(name);\n } catch {\n error(`${label} is not a valid header name`);\n continue;\n }\n try {\n validateHeaderValue(name, value);\n } catch {\n error(`${label} has an invalid header value`);\n continue;\n }\n if (FORBIDDEN_HEADERS.has(name.toLowerCase())) {\n error(`${label} is not allowed: aimock frames the body and sets this header itself`);\n }\n }\n }\n }\n\n if (raw.done !== undefined && typeof raw.done !== \"boolean\") {\n error(`raw.done must be a boolean; got ${JSON.stringify(raw.done)}`);\n } else if (raw.done !== undefined && wire !== undefined && wire !== \"openai-chat\") {\n error(\n `raw.done applies only to openai-chat (the only wire with a [DONE] terminal), not ${wire}`,\n );\n }\n\n return findings;\n}\n"],"mappings":"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"}