@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
package/dist/gemini.cjs CHANGED
@@ -1,13 +1,28 @@
1
+ const require_errors = require('./response/errors.cjs');
2
+ const require_policy = require('./response/policy.cjs');
1
3
  const require_helpers = require('./helpers.cjs');
2
4
  const require_sse_writer = require('./sse-writer.cjs');
3
5
  const require_chaos = require('./chaos.cjs');
4
6
  const require_misbehavior = require('./misbehavior.cjs');
5
7
  const require_router = require('./router.cjs');
6
8
  const require_recorder = require('./recorder.cjs');
7
- const require_interruption = require('./interruption.cjs');
9
+ const require_logger = require('./logger.cjs');
10
+ const require_timing = require('./response/timing.cjs');
11
+ const require_deliver = require('./response/deliver.cjs');
12
+ const require_proxy = require('./response/proxy.cjs');
13
+ const require_raw = require('./response/raw.cjs');
14
+ const require_finish = require('./response/finish.cjs');
15
+ const require_gemini = require('./response/usage/codecs/gemini.cjs');
8
16
 
9
17
  //#region src/gemini.ts
10
18
  /**
19
+ * Google Gemini GenerateContent API support.
20
+ *
21
+ * Translates incoming Gemini requests into the ChatCompletionRequest format
22
+ * used by the fixture router, and converts fixture responses back into the
23
+ * Gemini GenerateContent streaming (or non-streaming) format.
24
+ */
25
+ /**
11
26
  * Validate the shape of a Gemini `generateContent` body.
12
27
  *
13
28
  * Returns an error detail string when the shape is wrong, or null when
@@ -133,26 +148,115 @@ function geminiToCompletionRequest(req, model, stream) {
133
148
  }
134
149
  function geminiFinishReason(finishReason, defaultReason) {
135
150
  if (!finishReason) return defaultReason;
136
- if (finishReason === "stop") return "STOP";
137
- if (finishReason === "tool_calls") return "FUNCTION_CALL";
138
- if (finishReason === "length") return "MAX_TOKENS";
139
- if (finishReason === "content_filter") return "SAFETY";
140
- return finishReason;
151
+ return require_finish.mapGeminiFinish(finishReason);
141
152
  }
142
153
  function geminiUsageMetadata(overrides) {
143
- if (!overrides?.usage) return {
144
- promptTokenCount: 0,
145
- candidatesTokenCount: 0,
146
- totalTokenCount: 0
154
+ return require_gemini.render(overrides);
155
+ }
156
+ function geminiWholeTextPart(text, partIndex) {
157
+ return [{
158
+ partIndex,
159
+ start: 0,
160
+ end: text.length
161
+ }];
162
+ }
163
+ function geminiGroundingSupports(text, citations, textParts) {
164
+ const segment = (part, from, to) => {
165
+ const partText = text.slice(part.start, part.end);
166
+ const start = Math.min(Math.max(from - part.start, 0), partText.length);
167
+ const end = Math.min(Math.max(to - part.start, start), partText.length);
168
+ const byteOffset = (charIndex) => Buffer.byteLength(partText.slice(0, charIndex), "utf8");
169
+ return {
170
+ partIndex: part.partIndex,
171
+ startIndex: byteOffset(start),
172
+ endIndex: byteOffset(end),
173
+ text: partText.slice(start, end)
174
+ };
147
175
  };
148
- const prompt = overrides.usage.promptTokenCount ?? overrides.usage.prompt_tokens ?? overrides.usage.input_tokens ?? 0;
149
- const candidates = overrides.usage.candidatesTokenCount ?? overrides.usage.completion_tokens ?? overrides.usage.output_tokens ?? 0;
176
+ return citations.flatMap((c, i) => {
177
+ const spanned = textParts.filter((p) => Math.max(c.startIndex, p.start) < Math.min(c.endIndex, p.end));
178
+ return (spanned.length > 0 ? spanned : [textParts.find((p) => c.startIndex < p.end) ?? textParts[textParts.length - 1]]).map((p) => ({
179
+ segment: segment(p, c.startIndex, c.endIndex),
180
+ groundingChunkIndices: [i]
181
+ }));
182
+ });
183
+ }
184
+ function geminiGroundingMetadata(text, overrides, textParts) {
185
+ const citations = require_helpers.resolveCitations(text, overrides?.citations);
186
+ if (citations.length === 0 || textParts.length === 0) return void 0;
150
187
  return {
151
- promptTokenCount: prompt,
152
- candidatesTokenCount: candidates,
153
- totalTokenCount: overrides.usage.totalTokenCount ?? prompt + candidates
188
+ groundingChunks: geminiGroundingChunks(citations),
189
+ groundingSupports: geminiGroundingSupports(text, citations, textParts)
154
190
  };
155
191
  }
192
+ function geminiGroundingChunks(citations) {
193
+ return citations.map((c) => ({ web: {
194
+ uri: c.url,
195
+ title: c.title
196
+ } }));
197
+ }
198
+ function geminiGroundingField(text, overrides, textParts) {
199
+ const groundingMetadata = geminiGroundingMetadata(text, overrides, textParts);
200
+ return groundingMetadata ? { groundingMetadata } : {};
201
+ }
202
+ function geminiStreamGroundingFields(text, overrides, spans) {
203
+ const fields = spans.map(() => ({}));
204
+ const citations = require_helpers.resolveCitations(text, overrides?.citations);
205
+ if (citations.length === 0 || spans.length === 0) return fields;
206
+ const textParts = spans.map((s, k) => ({
207
+ partIndex: k,
208
+ start: s.start,
209
+ end: s.end
210
+ }));
211
+ const groundingChunks = geminiGroundingChunks(citations);
212
+ for (const support of geminiGroundingSupports(text, citations, textParts)) {
213
+ const k = support.segment.partIndex;
214
+ (fields[k].groundingMetadata ??= {
215
+ groundingChunks,
216
+ groundingSupports: []
217
+ }).groundingSupports.push({
218
+ ...support,
219
+ segment: {
220
+ ...support.segment,
221
+ partIndex: 0
222
+ }
223
+ });
224
+ }
225
+ return fields;
226
+ }
227
+ function geminiTextChunkSpans(text, chunkSize, offset = 0) {
228
+ if (text.length === 0) return [{
229
+ start: offset,
230
+ end: offset
231
+ }];
232
+ const spans = [];
233
+ let start = offset;
234
+ for (const slice of require_helpers.surrogateSafeChunks(text, chunkSize)) {
235
+ spans.push({
236
+ start,
237
+ end: start + slice.length
238
+ });
239
+ start += slice.length;
240
+ }
241
+ return spans;
242
+ }
243
+ function geminiFileParts(overrides) {
244
+ return require_helpers.fixtureFiles(overrides?.files).map((f) => ({ inlineData: {
245
+ mimeType: f.mimeType,
246
+ data: f.data
247
+ } }));
248
+ }
249
+ function geminiFileChunks(overrides) {
250
+ const parts = geminiFileParts(overrides);
251
+ if (parts.length === 0) return [];
252
+ return [{ candidates: [{
253
+ content: {
254
+ role: "model",
255
+ parts
256
+ },
257
+ index: 0
258
+ }] }];
259
+ }
156
260
  function buildGeminiTextStreamChunks(content, chunkSize, reasoning, overrides) {
157
261
  const chunks = [];
158
262
  const effectiveFinish = geminiFinishReason(overrides?.finishReason, "STOP");
@@ -170,9 +274,11 @@ function buildGeminiTextStreamChunks(content, chunkSize, reasoning, overrides) {
170
274
  index: 0
171
275
  }] });
172
276
  }
173
- for (let i = 0; i < content.length; i += chunkSize) {
174
- const slice = content.slice(i, i + chunkSize);
175
- const isLast = i + chunkSize >= content.length;
277
+ chunks.push(...geminiFileChunks(overrides));
278
+ const grounding = geminiStreamGroundingFields(content, overrides, geminiTextChunkSpans(content, chunkSize));
279
+ const contentSlices = require_helpers.surrogateSafeChunks(content, chunkSize);
280
+ contentSlices.forEach((slice, k) => {
281
+ const isLast = k === contentSlices.length - 1;
176
282
  const chunk = {
177
283
  candidates: [{
178
284
  content: {
@@ -180,12 +286,13 @@ function buildGeminiTextStreamChunks(content, chunkSize, reasoning, overrides) {
180
286
  parts: [{ text: slice }]
181
287
  },
182
288
  index: 0,
183
- ...isLast ? { finishReason: effectiveFinish } : {}
289
+ ...isLast ? { finishReason: effectiveFinish } : {},
290
+ ...grounding[k]
184
291
  }],
185
292
  ...isLast ? { usageMetadata: usage } : {}
186
293
  };
187
294
  chunks.push(chunk);
188
- }
295
+ });
189
296
  if (content.length === 0) chunks.push({
190
297
  candidates: [{
191
298
  content: {
@@ -193,6 +300,7 @@ function buildGeminiTextStreamChunks(content, chunkSize, reasoning, overrides) {
193
300
  parts: [{ text: "" }]
194
301
  },
195
302
  finishReason: effectiveFinish,
303
+ ...grounding[0],
196
304
  index: 0
197
305
  }],
198
306
  usageMetadata: usage
@@ -223,6 +331,8 @@ function buildGeminiToolCallStreamChunks(toolCalls, chunkSize, logger, reasoning
223
331
  index: 0
224
332
  }] });
225
333
  }
334
+ chunks.push(...geminiFileChunks(overrides));
335
+ require_helpers.resolveCitations("", overrides?.citations);
226
336
  const parts = toolCalls.map((tc) => parseToolCallPart(tc, logger));
227
337
  chunks.push({
228
338
  candidates: [{
@@ -243,6 +353,8 @@ function buildGeminiTextResponse(content, reasoning, overrides) {
243
353
  text: reasoning,
244
354
  thought: true
245
355
  });
356
+ parts.push(...geminiFileParts(overrides));
357
+ const textParts = geminiWholeTextPart(content, parts.length);
246
358
  parts.push({ text: content });
247
359
  return {
248
360
  candidates: [{
@@ -251,17 +363,20 @@ function buildGeminiTextResponse(content, reasoning, overrides) {
251
363
  parts
252
364
  },
253
365
  finishReason: geminiFinishReason(overrides?.finishReason, "STOP"),
366
+ ...geminiGroundingField(content, overrides, textParts),
254
367
  index: 0
255
368
  }],
256
369
  usageMetadata: geminiUsageMetadata(overrides)
257
370
  };
258
371
  }
259
372
  function buildGeminiToolCallResponse(toolCalls, logger, reasoning, overrides) {
373
+ require_helpers.resolveCitations("", overrides?.citations);
260
374
  const parts = [];
261
375
  if (reasoning) parts.push({
262
376
  text: reasoning,
263
377
  thought: true
264
378
  });
379
+ parts.push(...geminiFileParts(overrides));
265
380
  parts.push(...toolCalls.map((tc) => parseToolCallPart(tc, logger)));
266
381
  return {
267
382
  candidates: [{
@@ -290,9 +405,19 @@ function buildGeminiContentWithToolCallsStreamChunks(content, toolCalls, chunkSi
290
405
  index: 0
291
406
  }] });
292
407
  }
408
+ chunks.push(...geminiFileChunks(overrides));
293
409
  if (blocks && blocks.length > 0) {
294
410
  const outcome = require_helpers.resolveFixtureBlockOutcome(blocks);
295
411
  const resolved = outcome.ordered;
412
+ const spans = [];
413
+ let offset = 0;
414
+ for (const block of resolved) {
415
+ if (block.type !== "text") continue;
416
+ spans.push(...geminiTextChunkSpans(block.text, chunkSize, offset));
417
+ offset += block.text.length;
418
+ }
419
+ const grounding = geminiStreamGroundingFields(outcome.content, overrides, spans);
420
+ let textChunk = 0;
296
421
  resolved.forEach((block, i) => {
297
422
  const isLast = i === resolved.length - 1;
298
423
  const finishReason = isLast ? geminiFinishReason(overrides?.finishReason, outcome.hasToolCalls ? "FUNCTION_CALL" : "STOP") : void 0;
@@ -322,47 +447,53 @@ function buildGeminiContentWithToolCallsStreamChunks(content, toolCalls, chunkSi
322
447
  parts: [{ text: "" }]
323
448
  },
324
449
  ...finishReason ? { finishReason } : {},
450
+ ...grounding[textChunk++],
325
451
  index: 0
326
452
  }],
327
453
  ...isLast ? { usageMetadata: geminiUsageMetadata(overrides) } : {}
328
454
  });
329
- else for (let j = 0; j < text.length; j += chunkSize) {
330
- const slice = text.slice(j, j + chunkSize);
331
- const lastSlice = j + chunkSize >= text.length;
332
- const sliceFinish = isLast && lastSlice ? finishReason : void 0;
333
- chunks.push({
334
- candidates: [{
335
- content: {
336
- role: "model",
337
- parts: [{ text: slice }]
338
- },
339
- ...sliceFinish ? { finishReason: sliceFinish } : {},
340
- index: 0
341
- }],
342
- ...isLast && lastSlice ? { usageMetadata: geminiUsageMetadata(overrides) } : {}
455
+ else {
456
+ const slices = require_helpers.surrogateSafeChunks(text, chunkSize);
457
+ slices.forEach((slice, j) => {
458
+ const lastSlice = j === slices.length - 1;
459
+ const sliceFinish = isLast && lastSlice ? finishReason : void 0;
460
+ chunks.push({
461
+ candidates: [{
462
+ content: {
463
+ role: "model",
464
+ parts: [{ text: slice }]
465
+ },
466
+ ...sliceFinish ? { finishReason: sliceFinish } : {},
467
+ ...grounding[textChunk++],
468
+ index: 0
469
+ }],
470
+ ...isLast && lastSlice ? { usageMetadata: geminiUsageMetadata(overrides) } : {}
471
+ });
343
472
  });
344
473
  }
345
474
  }
346
475
  });
347
476
  return chunks;
348
477
  }
478
+ const grounding = geminiStreamGroundingFields(content, overrides, geminiTextChunkSpans(content, chunkSize));
349
479
  if (content.length === 0) chunks.push({ candidates: [{
350
480
  content: {
351
481
  role: "model",
352
482
  parts: [{ text: "" }]
353
483
  },
484
+ ...grounding[0],
354
485
  index: 0
355
486
  }] });
356
- else for (let i = 0; i < content.length; i += chunkSize) {
357
- const slice = content.slice(i, i + chunkSize);
487
+ else require_helpers.surrogateSafeChunks(content, chunkSize).forEach((slice, k) => {
358
488
  chunks.push({ candidates: [{
359
489
  content: {
360
490
  role: "model",
361
491
  parts: [{ text: slice }]
362
492
  },
493
+ ...grounding[k],
363
494
  index: 0
364
495
  }] });
365
- }
496
+ });
366
497
  const parts = toolCalls.map((tc) => parseToolCallPart(tc, logger));
367
498
  chunks.push({
368
499
  candidates: [{
@@ -383,18 +514,31 @@ function buildGeminiContentWithToolCallsResponse(content, toolCalls, logger, rea
383
514
  text: reasoning,
384
515
  thought: true
385
516
  });
517
+ parts.push(...geminiFileParts(overrides));
386
518
  let blockHasTools;
519
+ let groundingText = content;
520
+ const textParts = [];
387
521
  if (blocks && blocks.length > 0) {
388
522
  const outcome = require_helpers.resolveFixtureBlockOutcome(blocks);
389
523
  const resolved = outcome.ordered;
390
524
  blockHasTools = outcome.hasToolCalls;
525
+ groundingText = outcome.content;
391
526
  for (const block of resolved) if (block.type === "toolCall") parts.push(parseToolCallPart({
392
527
  name: block.name,
393
528
  arguments: block.arguments,
394
529
  id: block.id
395
530
  }, logger));
396
- else parts.push({ text: block.text });
531
+ else {
532
+ const start = textParts.length > 0 ? textParts[textParts.length - 1].end : 0;
533
+ textParts.push({
534
+ partIndex: parts.length,
535
+ start,
536
+ end: start + block.text.length
537
+ });
538
+ parts.push({ text: block.text });
539
+ }
397
540
  } else {
541
+ textParts.push(...geminiWholeTextPart(content, parts.length));
398
542
  parts.push({ text: content });
399
543
  parts.push(...toolCalls.map((tc) => parseToolCallPart(tc, logger)));
400
544
  }
@@ -405,6 +549,7 @@ function buildGeminiContentWithToolCallsResponse(content, toolCalls, logger, rea
405
549
  parts
406
550
  },
407
551
  finishReason: geminiFinishReason(overrides?.finishReason, blockHasTools === false ? "STOP" : "FUNCTION_CALL"),
552
+ ...geminiGroundingField(groundingText, overrides, textParts),
408
553
  index: 0
409
554
  }],
410
555
  usageMetadata: geminiUsageMetadata(overrides)
@@ -440,11 +585,7 @@ function buildGeminiAudioResponse(audio, toolCalls, logger, effReasoning) {
440
585
  finishReason: toolCalls.length ? "FUNCTION_CALL" : "STOP",
441
586
  index: 0
442
587
  }],
443
- usageMetadata: {
444
- promptTokenCount: 0,
445
- candidatesTokenCount: 0,
446
- totalTokenCount: 0
447
- }
588
+ usageMetadata: require_gemini.render()
448
589
  };
449
590
  }
450
591
  function buildGeminiAudioStreamChunks(audio, toolCalls, logger, effReasoning) {
@@ -457,37 +598,22 @@ function buildGeminiAudioStreamChunks(audio, toolCalls, logger, effReasoning) {
457
598
  finishReason: toolCalls.length ? "FUNCTION_CALL" : "STOP",
458
599
  index: 0
459
600
  }],
460
- usageMetadata: {
461
- promptTokenCount: 0,
462
- candidatesTokenCount: 0,
463
- totalTokenCount: 0
464
- }
601
+ usageMetadata: require_gemini.render()
465
602
  }];
466
603
  }
467
- async function writeGeminiSSEStream(res, chunks, optionsOrLatency) {
468
- const opts = typeof optionsOrLatency === "number" ? { latency: optionsOrLatency } : optionsOrLatency ?? {};
469
- const latency = opts.latency ?? 0;
470
- const profile = opts.streamingProfile;
471
- const { recordedTimings, replaySpeed } = opts;
472
- const signal = opts.signal;
473
- const onChunkSent = opts.onChunkSent;
474
- if (res.writableEnded) return true;
475
- res.setHeader("Content-Type", "text/event-stream");
476
- res.setHeader("Cache-Control", "no-cache");
477
- res.setHeader("Connection", "keep-alive");
478
- let chunkIndex = 0;
479
- for (const chunk of chunks) {
480
- const chunkDelay = require_sse_writer.calculateDelay(chunkIndex, profile, latency, recordedTimings, replaySpeed);
481
- if (chunkDelay > 0) await require_sse_writer.delay(chunkDelay, signal);
482
- if (signal?.aborted) return false;
483
- if (res.writableEnded) return true;
484
- res.write(`data: ${JSON.stringify(chunk)}\n\n`);
485
- onChunkSent?.();
486
- if (signal?.aborted) return false;
487
- chunkIndex++;
488
- }
489
- if (!res.writableEnded) res.end();
490
- return true;
604
+ const GEMINI_SSE = require_sse_writer.sseCodec({ done: false });
605
+ const SILENT_LOGGER = new require_logger.Logger("silent");
606
+ /**
607
+ * The reasoning a misbehavior reply's non-streaming wait is sized with: the
608
+ * plan response's reasoning through the same model and strict gate the
609
+ * builders apply. The gate runs with a silent logger, so the builder's own
610
+ * warning stays the only one. A reasoning-only plan carries its reasoning on
611
+ * the plan, and `misbehaviorPayloadLength` reads it there.
612
+ */
613
+ function misbehaviorPayloadReasoning(plan, model, strict) {
614
+ const response = plan.response;
615
+ if (plan.reasoning !== void 0 || !(require_helpers.isCombinedFixtureResponse(response) || require_helpers.isTextResponse(response) || require_helpers.isToolCallResponse(response))) return;
616
+ return require_helpers.resolveReasoningForModel(response.reasoning, model, strict, SILENT_LOGGER);
491
617
  }
492
618
  /** Prepare native fault output once; the journal describes these exact parts. */
493
619
  function prepareGeminiMisbehavior(plan, request, streaming, chunkSize, logger, strict) {
@@ -520,7 +646,11 @@ function prepareGeminiMisbehavior(plan, request, streaming, chunkSize, logger, s
520
646
  candidate.finishReason = "UNEXPECTED_TOOL_CALL";
521
647
  chunks = [{ candidates: [candidate] }];
522
648
  } else if (fault === "stop-length-mid-tool") {
523
- candidate.content.parts = content ? [{ text: content }] : [];
649
+ const parts = geminiFileParts(overrides);
650
+ const textPartIndex = parts.length;
651
+ if (content) parts.push({ text: content });
652
+ candidate.content.parts = parts;
653
+ if (content) Object.assign(candidate, geminiGroundingField(content, overrides, geminiWholeTextPart(content, textPartIndex)));
524
654
  candidate.finishReason = "MAX_TOKENS";
525
655
  chunks = [{ candidates: [candidate] }];
526
656
  } else if (fault === "empty-response") {
@@ -555,13 +685,14 @@ function prepareGeminiMisbehavior(plan, request, streaming, chunkSize, logger, s
555
685
  arguments: JSON.stringify(part.functionCall.args),
556
686
  ...part.functionCall.id ? { id: part.functionCall.id } : {}
557
687
  }] : []);
558
- const usage = require_helpers.resolveUsage(void 0, request.messages.map((message) => typeof message.content === "string" ? message.content : (message.content ?? []).map((part) => part.text ?? "").join("")).join(""), parts.map((part) => part.text ?? (part.functionCall ? part.functionCall.name + JSON.stringify(part.functionCall.args) : "")).join(""));
688
+ const prompt = request.messages.map((message) => typeof message.content === "string" ? message.content : (message.content ?? []).map((part) => part.text ?? "").join("")).join("");
689
+ const output = parts.map((part) => part.text ?? (part.functionCall ? part.functionCall.name + JSON.stringify(part.functionCall.args) : "")).join("");
559
690
  for (const chunk of chunks) delete chunk.usageMetadata;
560
- chunks[chunks.length - 1].usageMetadata = {
561
- promptTokenCount: usage.prompt_tokens,
562
- candidatesTokenCount: usage.completion_tokens,
563
- totalTokenCount: usage.total_tokens
564
- };
691
+ chunks[chunks.length - 1].usageMetadata = require_gemini.render(void 0, {
692
+ kind: "applied-misbehavior",
693
+ promptText: prompt,
694
+ completionText: output
695
+ });
565
696
  return {
566
697
  chunks,
567
698
  summary: {
@@ -589,11 +720,11 @@ async function handleGemini(req, res, raw, model, streaming, fixtures, journal,
589
720
  fixture: null
590
721
  }
591
722
  });
592
- require_sse_writer.writeErrorResponse(res, 400, JSON.stringify({ error: {
723
+ require_sse_writer.writeErrorResponse(res, 400, require_errors.renderError("gemini", "validation", {
593
724
  message: `Malformed JSON body: ${detail}`,
594
- code: 400,
725
+ bodyCode: 400,
595
726
  status: "INVALID_ARGUMENT"
596
- } }));
727
+ }).body);
597
728
  return;
598
729
  }
599
730
  if (!require_helpers.isJsonObject(geminiReq)) {
@@ -607,11 +738,11 @@ async function handleGemini(req, res, raw, model, streaming, fixtures, journal,
607
738
  fixture: null
608
739
  }
609
740
  });
610
- require_sse_writer.writeErrorResponse(res, 400, JSON.stringify({ error: {
741
+ require_sse_writer.writeErrorResponse(res, 400, require_errors.renderError("gemini", "validation", {
611
742
  message: "Request body must be a JSON object",
612
- code: 400,
743
+ bodyCode: 400,
613
744
  status: "INVALID_ARGUMENT"
614
- } }));
745
+ }).body);
615
746
  return;
616
747
  }
617
748
  const geminiShapeError = validateGeminiBody(geminiReq);
@@ -626,18 +757,21 @@ async function handleGemini(req, res, raw, model, streaming, fixtures, journal,
626
757
  fixture: null
627
758
  }
628
759
  });
629
- require_sse_writer.writeErrorResponse(res, 400, JSON.stringify({ error: {
760
+ require_sse_writer.writeErrorResponse(res, 400, require_errors.renderError("gemini", "validation", {
630
761
  message: `Invalid argument: ${geminiShapeError}`,
631
- code: 400,
762
+ bodyCode: 400,
632
763
  status: "INVALID_ARGUMENT"
633
- } }));
764
+ }).body);
634
765
  return;
635
766
  }
636
767
  const completionReq = geminiToCompletionRequest(geminiReq, model, streaming);
637
768
  completionReq._endpointType = "chat";
638
769
  completionReq._context = require_helpers.getContext(req);
639
770
  const testId = require_helpers.getTestId(req);
640
- const { fixture, skippedBySequenceOrTurn } = require_router.matchFixtureDiagnostic(fixtures, completionReq, journal.getFixtureMatchCountsForTest(testId), defaults.requestTransform, require_router.recordMatchOptions(!!defaults.record, defaults.logger));
771
+ const { fixture, skippedBySequenceOrTurn } = require_router.matchFixtureDiagnostic(fixtures, completionReq, journal.getFixtureMatchCountsForTest(testId), defaults.requestTransform, {
772
+ ...require_router.recordMatchOptions(!!defaults.record, defaults.logger),
773
+ wire: "gemini"
774
+ });
641
775
  const path = req.url ?? `/v1beta/models/${model}:generateContent`;
642
776
  if (fixture) logger.debug(`Fixture matched: ${JSON.stringify(fixture.match).slice(0, 120)}`);
643
777
  else logger.debug(`No fixture matched for request`);
@@ -649,7 +783,8 @@ async function handleGemini(req, res, raw, model, streaming, fixtures, journal,
649
783
  body: completionReq
650
784
  }, fixture ? "fixture" : "proxy", defaults.registry, defaults.logger)) return;
651
785
  if (!fixture) {
652
- if (require_helpers.resolveStrictMode(defaults.strict, req.headers)) {
786
+ const decisions = require_policy.resolveRequestDecisions(defaults.strict, req.headers);
787
+ if (decisions.fixtureMiss) {
653
788
  const strictMessage = require_helpers.strictNoMatchMessage(skippedBySequenceOrTurn);
654
789
  logger.error(require_helpers.strictNoMatchLogLine(req.method ?? "POST", path, skippedBySequenceOrTurn));
655
790
  journal.add({
@@ -660,18 +795,18 @@ async function handleGemini(req, res, raw, model, streaming, fixtures, journal,
660
795
  response: {
661
796
  status: 503,
662
797
  fixture: null,
663
- ...require_helpers.strictOverrideField(defaults.strict, req.headers)
798
+ ...require_policy.strictOverrideField(defaults.strict, req.headers)
664
799
  }
665
800
  });
666
- require_sse_writer.writeErrorResponse(res, 503, JSON.stringify({ error: {
801
+ require_sse_writer.writeErrorResponse(res, 503, require_errors.renderError("gemini", "strict-miss", {
667
802
  message: strictMessage,
668
- code: 503,
803
+ bodyCode: 503,
669
804
  status: "UNAVAILABLE"
670
- } }));
805
+ }).body);
671
806
  return;
672
807
  }
673
- if (defaults.record) {
674
- const outcome = await require_recorder.proxyAndRecord(req, res, completionReq, providerKey, path, fixtures, defaults, raw);
808
+ if (decisions.upstream && defaults.record) {
809
+ const { outcome, clientHungUp } = await require_proxy.withHangUpDetection(req, res, () => require_recorder.proxyAndRecord(req, res, completionReq, providerKey, path, fixtures, defaults, raw));
675
810
  if (outcome === "handled_by_hook") return;
676
811
  if (outcome !== "not_configured") {
677
812
  journal.add({
@@ -682,7 +817,8 @@ async function handleGemini(req, res, raw, model, streaming, fixtures, journal,
682
817
  response: {
683
818
  status: res.statusCode ?? 200,
684
819
  fixture: null,
685
- source: "proxy"
820
+ source: "proxy",
821
+ ...require_proxy.proxyInterruption(res, clientHungUp)
686
822
  }
687
823
  });
688
824
  return;
@@ -696,14 +832,14 @@ async function handleGemini(req, res, raw, model, streaming, fixtures, journal,
696
832
  response: {
697
833
  status: 404,
698
834
  fixture: null,
699
- ...require_helpers.strictOverrideField(defaults.strict, req.headers)
835
+ ...require_policy.strictOverrideField(defaults.strict, req.headers)
700
836
  }
701
837
  });
702
- require_sse_writer.writeErrorResponse(res, 404, JSON.stringify({ error: {
838
+ require_sse_writer.writeErrorResponse(res, 404, require_errors.renderError("gemini", "fixture-miss", {
703
839
  message: "No fixture matched",
704
- code: 404,
840
+ bodyCode: 404,
705
841
  status: "NOT_FOUND"
706
- } }));
842
+ }).body);
707
843
  return;
708
844
  }
709
845
  const response = await require_helpers.resolveResponse(fixture, completionReq);
@@ -736,18 +872,31 @@ async function handleGemini(req, res, raw, model, streaming, fixtures, journal,
736
872
  testId
737
873
  });
738
874
  if (misbehavior.summary?.evaluations.length === 0) logger.error(`${req.method ?? "POST"} ${path}: ${misbehavior.message}`);
739
- require_sse_writer.writeErrorResponse(res, misbehavior.status, JSON.stringify({ error: {
740
- code: misbehavior.status,
875
+ require_sse_writer.writeErrorResponse(res, misbehavior.status, require_errors.renderError("gemini", "misbehavior", {
876
+ bodyCode: misbehavior.status,
741
877
  message: misbehavior.message,
742
878
  status: misbehavior.status === 400 ? "INVALID_ARGUMENT" : "UNIMPLEMENTED"
743
- } }));
879
+ }).body);
744
880
  return;
745
881
  }
746
882
  const latency = fixture.latency ?? defaults.latency;
747
883
  const chunkSize = Math.max(1, fixture.chunkSize ?? defaults.chunkSize);
748
884
  const replaySpeed = fixture.replaySpeed ?? defaults.replaySpeed;
885
+ const streamTiming = {
886
+ latency,
887
+ streamingProfile: fixture.streamingProfile,
888
+ recordedTimings: fixture.recordedTimings,
889
+ replaySpeed
890
+ };
891
+ const jsonOpts = (payloadLength, duplicateId = false) => ({
892
+ surface: "other",
893
+ payloadLength,
894
+ chunkSize,
895
+ recordedTimings: fixture.recordedTimings,
896
+ duplicateId,
897
+ replaySpeed
898
+ });
749
899
  if (misbehavior.kind === "applied") {
750
- const prepared = prepareGeminiMisbehavior(misbehavior, completionReq, streaming, chunkSize, logger, require_helpers.resolveStrictMode(defaults.strict, req.headers));
751
900
  const entry = journal.add({
752
901
  method: req.method ?? "POST",
753
902
  path,
@@ -758,6 +907,8 @@ async function handleGemini(req, res, raw, model, streaming, fixtures, journal,
758
907
  fixture
759
908
  }
760
909
  });
910
+ const strictReasoning = require_policy.resolveRequestDecisions(defaults.strict, req.headers).reasoningSuppression;
911
+ const prepared = prepareGeminiMisbehavior(misbehavior, completionReq, streaming, chunkSize, logger, strictReasoning);
761
912
  require_misbehavior.recordMisbehaviorOutcome({
762
913
  entry,
763
914
  summary: prepared.summary,
@@ -765,24 +916,26 @@ async function handleGemini(req, res, raw, model, streaming, fixtures, journal,
765
916
  testId
766
917
  });
767
918
  if (!streaming) {
768
- res.writeHead(200, { "Content-Type": "application/json" });
769
- res.end(JSON.stringify(prepared.chunks[0]));
770
- } else {
771
- const interruption = require_interruption.createInterruptionSignal(fixture);
772
- if (!await writeGeminiSSEStream(res, prepared.chunks, {
773
- latency,
774
- streamingProfile: fixture.streamingProfile,
775
- recordedTimings: fixture.recordedTimings,
776
- replaySpeed,
777
- signal: interruption?.signal,
778
- onChunkSent: interruption?.tick
779
- })) {
780
- if (!res.writableEnded) res.destroy();
781
- entry.response.interrupted = true;
782
- entry.response.interruptReason = interruption?.reason();
783
- }
784
- interruption?.cleanup();
785
- }
919
+ const preparedBody = prepared.chunks[0];
920
+ await require_deliver.deliverJson(res, entry, fixture, () => preparedBody, jsonOpts(require_timing.misbehaviorPayloadLength(misbehavior, misbehaviorPayloadReasoning(misbehavior, completionReq.model, strictReasoning)), !!misbehavior.duplicateId));
921
+ } else await require_deliver.deliverStream(res, entry, fixture, GEMINI_SSE, prepared.chunks, streamTiming);
922
+ return;
923
+ }
924
+ if (require_helpers.isRawResponse(response)) {
925
+ await require_raw.serveRawResponse({
926
+ wire: "gemini",
927
+ stream: streaming,
928
+ req,
929
+ res,
930
+ fixture,
931
+ response,
932
+ body: completionReq,
933
+ journal,
934
+ defaults,
935
+ testId,
936
+ misbehaviorSummary: misbehavior.summary,
937
+ errorWire: "gemini"
938
+ });
786
939
  return;
787
940
  }
788
941
  if (require_helpers.isErrorResponse(response)) {
@@ -802,16 +955,15 @@ async function handleGemini(req, res, raw, model, streaming, fixtures, journal,
802
955
  defaults,
803
956
  testId
804
957
  });
805
- const geminiError = { error: {
806
- code: status,
958
+ require_sse_writer.writeErrorResponse(res, status, require_errors.renderError("gemini", "fixture", {
959
+ bodyCode: status,
807
960
  message: response.error.message,
808
961
  status: response.error.type ?? "ERROR"
809
- } };
810
- require_sse_writer.writeErrorResponse(res, status, JSON.stringify(geminiError), { retryAfter: response.retryAfter });
962
+ }).body, { retryAfter: response.retryAfter });
811
963
  return;
812
964
  }
813
965
  if (require_helpers.isAudioResponse(response)) {
814
- const effectiveStrict = require_helpers.resolveStrictMode(defaults.strict, req.headers);
966
+ const effectiveStrict = require_policy.resolveRequestDecisions(defaults.strict, req.headers).reasoningSuppression;
815
967
  const effReasoning = require_helpers.resolveReasoningForModel(response.reasoning, model, effectiveStrict, defaults.logger);
816
968
  const journalEntry = journal.add({
817
969
  method: req.method ?? "POST",
@@ -830,33 +982,14 @@ async function handleGemini(req, res, raw, model, streaming, fixtures, journal,
830
982
  testId
831
983
  });
832
984
  const audioToolCalls = Array.isArray(response.toolCalls) ? require_helpers.requireServedFunctionToolCalls(response, wire) : [];
833
- if (!streaming) {
834
- const body = buildGeminiAudioResponse(response, audioToolCalls, logger, effReasoning);
835
- res.writeHead(200, { "Content-Type": "application/json" });
836
- res.end(JSON.stringify(body));
837
- } else {
838
- const chunks = buildGeminiAudioStreamChunks(response, audioToolCalls, logger, effReasoning);
839
- const interruption = require_interruption.createInterruptionSignal(fixture);
840
- if (!await writeGeminiSSEStream(res, chunks, {
841
- latency,
842
- streamingProfile: fixture.streamingProfile,
843
- recordedTimings: fixture.recordedTimings,
844
- replaySpeed,
845
- signal: interruption?.signal,
846
- onChunkSent: interruption?.tick
847
- })) {
848
- if (!res.writableEnded) res.destroy();
849
- journalEntry.response.interrupted = true;
850
- journalEntry.response.interruptReason = interruption?.reason();
851
- }
852
- interruption?.cleanup();
853
- }
985
+ if (!streaming) await require_deliver.deliverJson(res, journalEntry, fixture, () => buildGeminiAudioResponse(response, audioToolCalls, logger, effReasoning), jsonOpts(require_timing.servedPayloadLength(response, effReasoning)));
986
+ else await require_deliver.deliverStream(res, journalEntry, fixture, GEMINI_SSE, buildGeminiAudioStreamChunks(response, audioToolCalls, logger, effReasoning), streamTiming);
854
987
  return;
855
988
  }
856
989
  if (require_helpers.isCombinedFixtureResponse(response)) {
857
990
  if (response.webSearches?.length) logger.warn("webSearches in fixture response are not supported for Gemini API — ignoring");
858
991
  const overrides = require_helpers.extractOverrides(response);
859
- const effectiveStrict = require_helpers.resolveStrictMode(defaults.strict, req.headers);
992
+ const effectiveStrict = require_policy.resolveRequestDecisions(defaults.strict, req.headers).reasoningSuppression;
860
993
  const effReasoning = require_helpers.resolveReasoningForModel(response.reasoning, model, effectiveStrict, defaults.logger);
861
994
  const journalEntry = journal.add({
862
995
  method: req.method ?? "POST",
@@ -875,33 +1008,14 @@ async function handleGemini(req, res, raw, model, streaming, fixtures, journal,
875
1008
  testId
876
1009
  });
877
1010
  const functionToolCalls = require_helpers.requireEmittedFunctionToolCalls(response, wire);
878
- if (!streaming) {
879
- const body = buildGeminiContentWithToolCallsResponse(response.content ?? "", functionToolCalls, logger, effReasoning, overrides, response.blocks);
880
- res.writeHead(200, { "Content-Type": "application/json" });
881
- res.end(JSON.stringify(body));
882
- } else {
883
- const chunks = buildGeminiContentWithToolCallsStreamChunks(response.content ?? "", functionToolCalls, chunkSize, logger, effReasoning, overrides, response.blocks);
884
- const interruption = require_interruption.createInterruptionSignal(fixture);
885
- if (!await writeGeminiSSEStream(res, chunks, {
886
- latency,
887
- streamingProfile: fixture.streamingProfile,
888
- recordedTimings: fixture.recordedTimings,
889
- replaySpeed,
890
- signal: interruption?.signal,
891
- onChunkSent: interruption?.tick
892
- })) {
893
- if (!res.writableEnded) res.destroy();
894
- journalEntry.response.interrupted = true;
895
- journalEntry.response.interruptReason = interruption?.reason();
896
- }
897
- interruption?.cleanup();
898
- }
1011
+ if (!streaming) await require_deliver.deliverJson(res, journalEntry, fixture, () => buildGeminiContentWithToolCallsResponse(response.content ?? "", functionToolCalls, logger, effReasoning, overrides, response.blocks), jsonOpts(require_timing.servedPayloadLength(response, effReasoning)));
1012
+ else await require_deliver.deliverStream(res, journalEntry, fixture, GEMINI_SSE, buildGeminiContentWithToolCallsStreamChunks(response.content ?? "", functionToolCalls, chunkSize, logger, effReasoning, overrides, response.blocks), streamTiming);
899
1013
  return;
900
1014
  }
901
1015
  if (require_helpers.isTextResponse(response)) {
902
1016
  if (response.webSearches?.length) logger.warn("webSearches in fixture response are not supported for Gemini API — ignoring");
903
1017
  const overrides = require_helpers.extractOverrides(response);
904
- const effectiveStrict = require_helpers.resolveStrictMode(defaults.strict, req.headers);
1018
+ const effectiveStrict = require_policy.resolveRequestDecisions(defaults.strict, req.headers).reasoningSuppression;
905
1019
  const effReasoning = require_helpers.resolveReasoningForModel(response.reasoning, model, effectiveStrict, defaults.logger);
906
1020
  const journalEntry = journal.add({
907
1021
  method: req.method ?? "POST",
@@ -919,33 +1033,14 @@ async function handleGemini(req, res, raw, model, streaming, fixtures, journal,
919
1033
  defaults,
920
1034
  testId
921
1035
  });
922
- if (!streaming) {
923
- const body = buildGeminiTextResponse(response.content, effReasoning, overrides);
924
- res.writeHead(200, { "Content-Type": "application/json" });
925
- res.end(JSON.stringify(body));
926
- } else {
927
- const chunks = buildGeminiTextStreamChunks(response.content, chunkSize, effReasoning, overrides);
928
- const interruption = require_interruption.createInterruptionSignal(fixture);
929
- if (!await writeGeminiSSEStream(res, chunks, {
930
- latency,
931
- streamingProfile: fixture.streamingProfile,
932
- recordedTimings: fixture.recordedTimings,
933
- replaySpeed,
934
- signal: interruption?.signal,
935
- onChunkSent: interruption?.tick
936
- })) {
937
- if (!res.writableEnded) res.destroy();
938
- journalEntry.response.interrupted = true;
939
- journalEntry.response.interruptReason = interruption?.reason();
940
- }
941
- interruption?.cleanup();
942
- }
1036
+ if (!streaming) await require_deliver.deliverJson(res, journalEntry, fixture, () => buildGeminiTextResponse(response.content, effReasoning, overrides), jsonOpts(require_timing.servedPayloadLength(response, effReasoning)));
1037
+ else await require_deliver.deliverStream(res, journalEntry, fixture, GEMINI_SSE, buildGeminiTextStreamChunks(response.content, chunkSize, effReasoning, overrides), streamTiming);
943
1038
  return;
944
1039
  }
945
1040
  if (require_helpers.isToolCallResponse(response)) {
946
1041
  if (response.webSearches?.length) logger.warn("webSearches in fixture response are not supported for Gemini API — ignoring");
947
1042
  const overrides = require_helpers.extractOverrides(response);
948
- const effectiveStrict = require_helpers.resolveStrictMode(defaults.strict, req.headers);
1043
+ const effectiveStrict = require_policy.resolveRequestDecisions(defaults.strict, req.headers).reasoningSuppression;
949
1044
  const effReasoning = require_helpers.resolveReasoningForModel(response.reasoning, model, effectiveStrict, defaults.logger);
950
1045
  const journalEntry = journal.add({
951
1046
  method: req.method ?? "POST",
@@ -964,27 +1059,8 @@ async function handleGemini(req, res, raw, model, streaming, fixtures, journal,
964
1059
  testId
965
1060
  });
966
1061
  const functionToolCalls = require_helpers.requireEmittedFunctionToolCalls(response, wire);
967
- if (!streaming) {
968
- const body = buildGeminiToolCallResponse(functionToolCalls, logger, effReasoning, overrides);
969
- res.writeHead(200, { "Content-Type": "application/json" });
970
- res.end(JSON.stringify(body));
971
- } else {
972
- const chunks = buildGeminiToolCallStreamChunks(functionToolCalls, chunkSize, logger, effReasoning, overrides);
973
- const interruption = require_interruption.createInterruptionSignal(fixture);
974
- if (!await writeGeminiSSEStream(res, chunks, {
975
- latency,
976
- streamingProfile: fixture.streamingProfile,
977
- recordedTimings: fixture.recordedTimings,
978
- replaySpeed,
979
- signal: interruption?.signal,
980
- onChunkSent: interruption?.tick
981
- })) {
982
- if (!res.writableEnded) res.destroy();
983
- journalEntry.response.interrupted = true;
984
- journalEntry.response.interruptReason = interruption?.reason();
985
- }
986
- interruption?.cleanup();
987
- }
1062
+ if (!streaming) await require_deliver.deliverJson(res, journalEntry, fixture, () => buildGeminiToolCallResponse(functionToolCalls, logger, effReasoning, overrides), jsonOpts(require_timing.servedPayloadLength(response, effReasoning)));
1063
+ else await require_deliver.deliverStream(res, journalEntry, fixture, GEMINI_SSE, buildGeminiToolCallStreamChunks(functionToolCalls, chunkSize, logger, effReasoning, overrides), streamTiming);
988
1064
  return;
989
1065
  }
990
1066
  require_misbehavior.recordMisbehaviorOutcome({
@@ -1002,13 +1078,14 @@ async function handleGemini(req, res, raw, model, streaming, fixtures, journal,
1002
1078
  defaults,
1003
1079
  testId
1004
1080
  });
1005
- require_sse_writer.writeErrorResponse(res, 500, JSON.stringify({ error: {
1081
+ require_sse_writer.writeErrorResponse(res, 500, require_errors.renderError("gemini", "unknown-response", {
1006
1082
  message: "Fixture response did not match any known type",
1007
- code: 500,
1083
+ bodyCode: 500,
1008
1084
  status: "INTERNAL"
1009
- } }));
1085
+ }).body);
1010
1086
  }
1011
1087
 
1012
1088
  //#endregion
1089
+ exports.geminiToCompletionRequest = geminiToCompletionRequest;
1013
1090
  exports.handleGemini = handleGemini;
1014
1091
  //# sourceMappingURL=gemini.cjs.map