@copilotkit/aimock 1.45.1 → 1.46.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 (425) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +13 -0
  4. package/README.md +7 -1
  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/batches.cjs +2 -4
  25. package/dist/batches.cjs.map +1 -1
  26. package/dist/batches.d.cts.map +1 -1
  27. package/dist/batches.d.ts.map +1 -1
  28. package/dist/batches.js +2 -4
  29. package/dist/batches.js.map +1 -1
  30. package/dist/bedrock-converse.cjs +61 -80
  31. package/dist/bedrock-converse.cjs.map +1 -1
  32. package/dist/bedrock-converse.d.cts.map +1 -1
  33. package/dist/bedrock-converse.d.ts.map +1 -1
  34. package/dist/bedrock-converse.js +58 -77
  35. package/dist/bedrock-converse.js.map +1 -1
  36. package/dist/bedrock.cjs +65 -97
  37. package/dist/bedrock.cjs.map +1 -1
  38. package/dist/bedrock.d.cts.map +1 -1
  39. package/dist/bedrock.d.ts.map +1 -1
  40. package/dist/bedrock.js +62 -94
  41. package/dist/bedrock.js.map +1 -1
  42. package/dist/byteplus-video.cjs +11 -10
  43. package/dist/byteplus-video.cjs.map +1 -1
  44. package/dist/byteplus-video.d.cts.map +1 -1
  45. package/dist/byteplus-video.d.ts.map +1 -1
  46. package/dist/byteplus-video.js +5 -4
  47. package/dist/byteplus-video.js.map +1 -1
  48. package/dist/chaos.cjs +5 -4
  49. package/dist/chaos.cjs.map +1 -1
  50. package/dist/chaos.d.cts.map +1 -1
  51. package/dist/chaos.d.ts.map +1 -1
  52. package/dist/chaos.js +5 -4
  53. package/dist/chaos.js.map +1 -1
  54. package/dist/cli.cjs +15 -0
  55. package/dist/cli.cjs.map +1 -1
  56. package/dist/cli.js +15 -0
  57. package/dist/cli.js.map +1 -1
  58. package/dist/cohere.cjs +49 -74
  59. package/dist/cohere.cjs.map +1 -1
  60. package/dist/cohere.d.cts.map +1 -1
  61. package/dist/cohere.d.ts.map +1 -1
  62. package/dist/cohere.js +47 -72
  63. package/dist/cohere.js.map +1 -1
  64. package/dist/config-loader.cjs +29 -1
  65. package/dist/config-loader.cjs.map +1 -1
  66. package/dist/config-loader.d.cts +7 -1
  67. package/dist/config-loader.d.cts.map +1 -1
  68. package/dist/config-loader.d.ts +7 -1
  69. package/dist/config-loader.d.ts.map +1 -1
  70. package/dist/config-loader.js +29 -2
  71. package/dist/config-loader.js.map +1 -1
  72. package/dist/count-tokens.cjs +146 -0
  73. package/dist/count-tokens.cjs.map +1 -0
  74. package/dist/count-tokens.js +146 -0
  75. package/dist/count-tokens.js.map +1 -0
  76. package/dist/elevenlabs-audio.cjs +36 -34
  77. package/dist/elevenlabs-audio.cjs.map +1 -1
  78. package/dist/elevenlabs-audio.d.cts.map +1 -1
  79. package/dist/elevenlabs-audio.d.ts.map +1 -1
  80. package/dist/elevenlabs-audio.js +33 -31
  81. package/dist/elevenlabs-audio.js.map +1 -1
  82. package/dist/elevenlabs-voice.cjs +38 -37
  83. package/dist/elevenlabs-voice.cjs.map +1 -1
  84. package/dist/elevenlabs-voice.d.cts.map +1 -1
  85. package/dist/elevenlabs-voice.d.ts.map +1 -1
  86. package/dist/elevenlabs-voice.js +33 -32
  87. package/dist/elevenlabs-voice.js.map +1 -1
  88. package/dist/embedding-request.cjs +16 -0
  89. package/dist/embedding-request.cjs.map +1 -0
  90. package/dist/embedding-request.js +14 -0
  91. package/dist/embedding-request.js.map +1 -0
  92. package/dist/embeddings.cjs +30 -20
  93. package/dist/embeddings.cjs.map +1 -1
  94. package/dist/embeddings.d.cts.map +1 -1
  95. package/dist/embeddings.d.ts.map +1 -1
  96. package/dist/embeddings.js +30 -20
  97. package/dist/embeddings.js.map +1 -1
  98. package/dist/fal-audio.cjs +45 -43
  99. package/dist/fal-audio.cjs.map +1 -1
  100. package/dist/fal-audio.d.cts.map +1 -1
  101. package/dist/fal-audio.d.ts.map +1 -1
  102. package/dist/fal-audio.js +42 -40
  103. package/dist/fal-audio.js.map +1 -1
  104. package/dist/fal.cjs +17 -15
  105. package/dist/fal.cjs.map +1 -1
  106. package/dist/fal.js +16 -14
  107. package/dist/fal.js.map +1 -1
  108. package/dist/files.cjs +2 -4
  109. package/dist/files.cjs.map +1 -1
  110. package/dist/files.d.cts.map +1 -1
  111. package/dist/files.d.ts.map +1 -1
  112. package/dist/files.js +2 -4
  113. package/dist/files.js.map +1 -1
  114. package/dist/fine-tuning.cjs +2 -4
  115. package/dist/fine-tuning.cjs.map +1 -1
  116. package/dist/fine-tuning.d.cts.map +1 -1
  117. package/dist/fine-tuning.d.ts.map +1 -1
  118. package/dist/fine-tuning.js +2 -4
  119. package/dist/fine-tuning.js.map +1 -1
  120. package/dist/fixture-loader.cjs +37 -42
  121. package/dist/fixture-loader.cjs.map +1 -1
  122. package/dist/fixture-loader.d.cts.map +1 -1
  123. package/dist/fixture-loader.d.ts.map +1 -1
  124. package/dist/fixture-loader.js +37 -42
  125. package/dist/fixture-loader.js.map +1 -1
  126. package/dist/gemini-embeddings.cjs +26 -24
  127. package/dist/gemini-embeddings.cjs.map +1 -1
  128. package/dist/gemini-embeddings.js +26 -24
  129. package/dist/gemini-embeddings.js.map +1 -1
  130. package/dist/gemini-interactions.cjs +50 -35
  131. package/dist/gemini-interactions.cjs.map +1 -1
  132. package/dist/gemini-interactions.d.cts +0 -1
  133. package/dist/gemini-interactions.d.cts.map +1 -1
  134. package/dist/gemini-interactions.d.ts +0 -1
  135. package/dist/gemini-interactions.d.ts.map +1 -1
  136. package/dist/gemini-interactions.js +49 -34
  137. package/dist/gemini-interactions.js.map +1 -1
  138. package/dist/gemini.cjs +57 -67
  139. package/dist/gemini.cjs.map +1 -1
  140. package/dist/gemini.d.cts.map +1 -1
  141. package/dist/gemini.d.ts.map +1 -1
  142. package/dist/gemini.js +56 -67
  143. package/dist/gemini.js.map +1 -1
  144. package/dist/grok-video.cjs +14 -12
  145. package/dist/grok-video.cjs.map +1 -1
  146. package/dist/grok-video.d.cts.map +1 -1
  147. package/dist/grok-video.d.ts.map +1 -1
  148. package/dist/grok-video.js +8 -6
  149. package/dist/grok-video.js.map +1 -1
  150. package/dist/helpers.cjs +11 -68
  151. package/dist/helpers.cjs.map +1 -1
  152. package/dist/helpers.d.cts.map +1 -1
  153. package/dist/helpers.d.ts.map +1 -1
  154. package/dist/helpers.js +12 -67
  155. package/dist/helpers.js.map +1 -1
  156. package/dist/images.cjs +30 -28
  157. package/dist/images.cjs.map +1 -1
  158. package/dist/images.d.cts.map +1 -1
  159. package/dist/images.d.ts.map +1 -1
  160. package/dist/images.js +27 -25
  161. package/dist/images.js.map +1 -1
  162. package/dist/index.d.cts +2 -2
  163. package/dist/index.d.ts +2 -2
  164. package/dist/journal.cjs +3 -1
  165. package/dist/journal.cjs.map +1 -1
  166. package/dist/journal.d.cts.map +1 -1
  167. package/dist/journal.d.ts.map +1 -1
  168. package/dist/journal.js +2 -1
  169. package/dist/journal.js.map +1 -1
  170. package/dist/llmock.cjs +3 -0
  171. package/dist/llmock.cjs.map +1 -1
  172. package/dist/llmock.d.cts.map +1 -1
  173. package/dist/llmock.d.ts.map +1 -1
  174. package/dist/llmock.js +3 -0
  175. package/dist/llmock.js.map +1 -1
  176. package/dist/mcp-handler.cjs +7 -3
  177. package/dist/mcp-handler.cjs.map +1 -1
  178. package/dist/mcp-handler.js +7 -3
  179. package/dist/mcp-handler.js.map +1 -1
  180. package/dist/mcp-recorder.cjs +2 -1
  181. package/dist/mcp-recorder.cjs.map +1 -1
  182. package/dist/mcp-recorder.js +3 -2
  183. package/dist/mcp-recorder.js.map +1 -1
  184. package/dist/messages.cjs +111 -96
  185. package/dist/messages.cjs.map +1 -1
  186. package/dist/messages.d.cts.map +1 -1
  187. package/dist/messages.d.ts.map +1 -1
  188. package/dist/messages.js +109 -95
  189. package/dist/messages.js.map +1 -1
  190. package/dist/metrics.cjs +5 -2
  191. package/dist/metrics.cjs.map +1 -1
  192. package/dist/metrics.d.cts.map +1 -1
  193. package/dist/metrics.d.ts.map +1 -1
  194. package/dist/metrics.js +6 -3
  195. package/dist/metrics.js.map +1 -1
  196. package/dist/model-utils.cjs +1 -0
  197. package/dist/model-utils.cjs.map +1 -1
  198. package/dist/model-utils.js +1 -1
  199. package/dist/model-utils.js.map +1 -1
  200. package/dist/moderation.cjs +15 -12
  201. package/dist/moderation.cjs.map +1 -1
  202. package/dist/moderation.js +14 -11
  203. package/dist/moderation.js.map +1 -1
  204. package/dist/ollama.cjs +128 -68
  205. package/dist/ollama.cjs.map +1 -1
  206. package/dist/ollama.d.cts.map +1 -1
  207. package/dist/ollama.d.ts.map +1 -1
  208. package/dist/ollama.js +124 -64
  209. package/dist/ollama.js.map +1 -1
  210. package/dist/openapi.cjs +323 -3
  211. package/dist/openapi.cjs.map +1 -1
  212. package/dist/openapi.d.cts.map +1 -1
  213. package/dist/openapi.d.ts.map +1 -1
  214. package/dist/openapi.js +324 -4
  215. package/dist/openapi.js.map +1 -1
  216. package/dist/openrouter-chat.cjs +11 -155
  217. package/dist/openrouter-chat.cjs.map +1 -1
  218. package/dist/openrouter-chat.js +11 -155
  219. package/dist/openrouter-chat.js.map +1 -1
  220. package/dist/openrouter-video.cjs +51 -74
  221. package/dist/openrouter-video.cjs.map +1 -1
  222. package/dist/openrouter-video.d.cts.map +1 -1
  223. package/dist/openrouter-video.d.ts.map +1 -1
  224. package/dist/openrouter-video.js +37 -60
  225. package/dist/openrouter-video.js.map +1 -1
  226. package/dist/recorder.cjs +176 -95
  227. package/dist/recorder.cjs.map +1 -1
  228. package/dist/recorder.d.cts.map +1 -1
  229. package/dist/recorder.d.ts.map +1 -1
  230. package/dist/recorder.js +176 -95
  231. package/dist/recorder.js.map +1 -1
  232. package/dist/rerank.cjs +13 -11
  233. package/dist/rerank.cjs.map +1 -1
  234. package/dist/rerank.js +12 -10
  235. package/dist/rerank.js.map +1 -1
  236. package/dist/response/catalog/anthropic-page.cjs +39 -0
  237. package/dist/response/catalog/anthropic-page.cjs.map +1 -0
  238. package/dist/response/catalog/anthropic-page.js +38 -0
  239. package/dist/response/catalog/anthropic-page.js.map +1 -0
  240. package/dist/response/catalog/collect.cjs +61 -0
  241. package/dist/response/catalog/collect.cjs.map +1 -0
  242. package/dist/response/catalog/collect.js +59 -0
  243. package/dist/response/catalog/collect.js.map +1 -0
  244. package/dist/response/catalog/gemini-page.cjs +25 -0
  245. package/dist/response/catalog/gemini-page.cjs.map +1 -0
  246. package/dist/response/catalog/gemini-page.js +24 -0
  247. package/dist/response/catalog/gemini-page.js.map +1 -0
  248. package/dist/response/catalog/render.cjs +182 -0
  249. package/dist/response/catalog/render.cjs.map +1 -0
  250. package/dist/response/catalog/render.js +171 -0
  251. package/dist/response/catalog/render.js.map +1 -0
  252. package/dist/response/errors.cjs +225 -0
  253. package/dist/response/errors.cjs.map +1 -0
  254. package/dist/response/errors.js +224 -0
  255. package/dist/response/errors.js.map +1 -0
  256. package/dist/response/finish.cjs +39 -0
  257. package/dist/response/finish.cjs.map +1 -0
  258. package/dist/response/finish.js +35 -0
  259. package/dist/response/finish.js.map +1 -0
  260. package/dist/response/policy.cjs +126 -0
  261. package/dist/response/policy.cjs.map +1 -0
  262. package/dist/response/policy.js +120 -0
  263. package/dist/response/policy.js.map +1 -0
  264. package/dist/response/profiles.cjs +69 -0
  265. package/dist/response/profiles.cjs.map +1 -0
  266. package/dist/response/profiles.js +65 -0
  267. package/dist/response/profiles.js.map +1 -0
  268. package/dist/response/usage/codecs/anthropic.cjs +52 -0
  269. package/dist/response/usage/codecs/anthropic.cjs.map +1 -0
  270. package/dist/response/usage/codecs/anthropic.js +50 -0
  271. package/dist/response/usage/codecs/anthropic.js.map +1 -0
  272. package/dist/response/usage/codecs/cohere.cjs +36 -0
  273. package/dist/response/usage/codecs/cohere.cjs.map +1 -0
  274. package/dist/response/usage/codecs/cohere.js +35 -0
  275. package/dist/response/usage/codecs/cohere.js.map +1 -0
  276. package/dist/response/usage/codecs/converse.cjs +16 -0
  277. package/dist/response/usage/codecs/converse.cjs.map +1 -0
  278. package/dist/response/usage/codecs/converse.js +15 -0
  279. package/dist/response/usage/codecs/converse.js.map +1 -0
  280. package/dist/response/usage/codecs/gemini.cjs +31 -0
  281. package/dist/response/usage/codecs/gemini.cjs.map +1 -0
  282. package/dist/response/usage/codecs/gemini.js +31 -0
  283. package/dist/response/usage/codecs/gemini.js.map +1 -0
  284. package/dist/response/usage/codecs/interactions.cjs +22 -0
  285. package/dist/response/usage/codecs/interactions.cjs.map +1 -0
  286. package/dist/response/usage/codecs/interactions.js +21 -0
  287. package/dist/response/usage/codecs/interactions.js.map +1 -0
  288. package/dist/response/usage/codecs/ollama.cjs +17 -0
  289. package/dist/response/usage/codecs/ollama.cjs.map +1 -0
  290. package/dist/response/usage/codecs/ollama.js +17 -0
  291. package/dist/response/usage/codecs/ollama.js.map +1 -0
  292. package/dist/response/usage/codecs/openai.cjs +52 -0
  293. package/dist/response/usage/codecs/openai.cjs.map +1 -0
  294. package/dist/response/usage/codecs/openai.js +50 -0
  295. package/dist/response/usage/codecs/openai.js.map +1 -0
  296. package/dist/response/usage/codecs/openrouter.cjs +68 -0
  297. package/dist/response/usage/codecs/openrouter.cjs.map +1 -0
  298. package/dist/response/usage/codecs/openrouter.js +67 -0
  299. package/dist/response/usage/codecs/openrouter.js.map +1 -0
  300. package/dist/response/usage/codecs/realtime.cjs +19 -0
  301. package/dist/response/usage/codecs/realtime.cjs.map +1 -0
  302. package/dist/response/usage/codecs/realtime.js +18 -0
  303. package/dist/response/usage/codecs/realtime.js.map +1 -0
  304. package/dist/response/usage/codecs/responses.cjs +21 -0
  305. package/dist/response/usage/codecs/responses.cjs.map +1 -0
  306. package/dist/response/usage/codecs/responses.js +20 -0
  307. package/dist/response/usage/codecs/responses.js.map +1 -0
  308. package/dist/response/usage/estimate.cjs +23 -0
  309. package/dist/response/usage/estimate.cjs.map +1 -0
  310. package/dist/response/usage/estimate.js +21 -0
  311. package/dist/response/usage/estimate.js.map +1 -0
  312. package/dist/response/usage/fields.cjs +72 -0
  313. package/dist/response/usage/fields.cjs.map +1 -0
  314. package/dist/response/usage/fields.js +70 -0
  315. package/dist/response/usage/fields.js.map +1 -0
  316. package/dist/response/usage/recording.cjs +52 -0
  317. package/dist/response/usage/recording.cjs.map +1 -0
  318. package/dist/response/usage/recording.js +52 -0
  319. package/dist/response/usage/recording.js.map +1 -0
  320. package/dist/responses.cjs +45 -58
  321. package/dist/responses.cjs.map +1 -1
  322. package/dist/responses.d.cts.map +1 -1
  323. package/dist/responses.d.ts.map +1 -1
  324. package/dist/responses.js +44 -57
  325. package/dist/responses.js.map +1 -1
  326. package/dist/route-registry.cjs +45 -0
  327. package/dist/route-registry.cjs.map +1 -1
  328. package/dist/route-registry.d.cts.map +1 -1
  329. package/dist/route-registry.d.ts.map +1 -1
  330. package/dist/route-registry.js +41 -1
  331. package/dist/route-registry.js.map +1 -1
  332. package/dist/router.cjs +4 -0
  333. package/dist/router.cjs.map +1 -1
  334. package/dist/router.d.cts.map +1 -1
  335. package/dist/router.d.ts.map +1 -1
  336. package/dist/router.js +3 -0
  337. package/dist/router.js.map +1 -1
  338. package/dist/search.cjs +13 -11
  339. package/dist/search.cjs.map +1 -1
  340. package/dist/search.js +12 -10
  341. package/dist/search.js.map +1 -1
  342. package/dist/server.cjs +222 -146
  343. package/dist/server.cjs.map +1 -1
  344. package/dist/server.d.cts.map +1 -1
  345. package/dist/server.d.ts.map +1 -1
  346. package/dist/server.js +223 -147
  347. package/dist/server.js.map +1 -1
  348. package/dist/speech.cjs +20 -18
  349. package/dist/speech.cjs.map +1 -1
  350. package/dist/speech.d.cts.map +1 -1
  351. package/dist/speech.d.ts.map +1 -1
  352. package/dist/speech.js +19 -17
  353. package/dist/speech.js.map +1 -1
  354. package/dist/sse-writer.cjs +7 -0
  355. package/dist/sse-writer.cjs.map +1 -1
  356. package/dist/sse-writer.d.cts.map +1 -1
  357. package/dist/sse-writer.d.ts.map +1 -1
  358. package/dist/sse-writer.js +7 -1
  359. package/dist/sse-writer.js.map +1 -1
  360. package/dist/stream-collapse.cjs +118 -11
  361. package/dist/stream-collapse.cjs.map +1 -1
  362. package/dist/stream-collapse.d.cts +10 -9
  363. package/dist/stream-collapse.d.cts.map +1 -1
  364. package/dist/stream-collapse.d.ts +10 -9
  365. package/dist/stream-collapse.d.ts.map +1 -1
  366. package/dist/stream-collapse.js +118 -11
  367. package/dist/stream-collapse.js.map +1 -1
  368. package/dist/transcription.cjs +12 -10
  369. package/dist/transcription.cjs.map +1 -1
  370. package/dist/transcription.d.cts.map +1 -1
  371. package/dist/transcription.d.ts.map +1 -1
  372. package/dist/transcription.js +11 -9
  373. package/dist/transcription.js.map +1 -1
  374. package/dist/types.cjs.map +1 -1
  375. package/dist/types.d.cts +62 -3
  376. package/dist/types.d.cts.map +1 -1
  377. package/dist/types.d.ts +62 -3
  378. package/dist/types.d.ts.map +1 -1
  379. package/dist/types.js.map +1 -1
  380. package/dist/vector-mock.cjs +3 -8
  381. package/dist/vector-mock.cjs.map +1 -1
  382. package/dist/vector-mock.d.cts.map +1 -1
  383. package/dist/vector-mock.d.ts.map +1 -1
  384. package/dist/vector-mock.js +3 -8
  385. package/dist/vector-mock.js.map +1 -1
  386. package/dist/vector-stores.cjs +2 -4
  387. package/dist/vector-stores.cjs.map +1 -1
  388. package/dist/vector-stores.d.cts.map +1 -1
  389. package/dist/vector-stores.d.ts.map +1 -1
  390. package/dist/vector-stores.js +2 -4
  391. package/dist/vector-stores.js.map +1 -1
  392. package/dist/veo-video.cjs +16 -14
  393. package/dist/veo-video.cjs.map +1 -1
  394. package/dist/veo-video.js +10 -8
  395. package/dist/veo-video.js.map +1 -1
  396. package/dist/video.cjs +21 -19
  397. package/dist/video.cjs.map +1 -1
  398. package/dist/video.d.cts.map +1 -1
  399. package/dist/video.d.ts.map +1 -1
  400. package/dist/video.js +20 -18
  401. package/dist/video.js.map +1 -1
  402. package/dist/ws-gemini-live.cjs +11 -3
  403. package/dist/ws-gemini-live.cjs.map +1 -1
  404. package/dist/ws-gemini-live.d.cts +0 -1
  405. package/dist/ws-gemini-live.d.cts.map +1 -1
  406. package/dist/ws-gemini-live.d.ts +0 -1
  407. package/dist/ws-gemini-live.d.ts.map +1 -1
  408. package/dist/ws-gemini-live.js +10 -2
  409. package/dist/ws-gemini-live.js.map +1 -1
  410. package/dist/ws-live.cjs +6 -5
  411. package/dist/ws-live.cjs.map +1 -1
  412. package/dist/ws-live.js +5 -4
  413. package/dist/ws-live.js.map +1 -1
  414. package/dist/ws-realtime.cjs +28 -54
  415. package/dist/ws-realtime.cjs.map +1 -1
  416. package/dist/ws-realtime.d.cts.map +1 -1
  417. package/dist/ws-realtime.d.ts.map +1 -1
  418. package/dist/ws-realtime.js +25 -51
  419. package/dist/ws-realtime.js.map +1 -1
  420. package/dist/ws-responses.cjs +8 -6
  421. package/dist/ws-responses.cjs.map +1 -1
  422. package/dist/ws-responses.js +7 -5
  423. package/dist/ws-responses.js.map +1 -1
  424. package/package.json +4 -1
  425. package/skills/write-fixtures/SKILL.md +25 -16
@@ -1 +1 @@
1
- {"version":3,"file":"recorder.d.cts","names":[],"sources":["../src/recorder.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;UAsOiB,qBAAA;;;QAGT;;UAGS,YAAA;;;;;;;;;;;;;;;;;;mCAkBkB,oCAAoC;;;;;;;;;;;;;;;;;;;;;;KAuB3D,YAAA;;;;;;;;;;;;;;;iBA8OU,cAAA,MACf,MAAA,CAAK,sBACL,MAAA,CAAK,yBACD,oCACI,+CAEH;WAEC;UACD;2BACiB,0BAA0B;mBAClC;+BAGT,eACT,QAAQ"}
1
+ {"version":3,"file":"recorder.d.cts","names":[],"sources":["../src/recorder.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;UA0OiB,qBAAA;;;QAGT;;UAGS,YAAA;;;;;;;;;;;;;;;;;;mCAkBkB,oCAAoC;;;;;;;;;;;;;;;;;;;;;;KAuB3D,YAAA;;;;;;;;;;;;;;;iBA8OU,cAAA,MACf,MAAA,CAAK,sBACL,MAAA,CAAK,yBACD,oCACI,+CAEH;WAEC;UACD;2BACiB,0BAA0B;mBAClC;+BAGT,eACT,QAAQ"}
@@ -1 +1 @@
1
- {"version":3,"file":"recorder.d.ts","names":[],"sources":["../src/recorder.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;UAsOiB,qBAAA;;;QAGT;;UAGS,YAAA;;;;;;;;;;;;;;;;;;mCAkBkB,oCAAoC;;;;;;;;;;;;;;;;;;;;;;KAuB3D,YAAA;;;;;;;;;;;;;;;iBA8OU,cAAA,MACf,MAAA,CAAK,sBACL,MAAA,CAAK,yBACD,oCACI,+CAEH;WAEC;UACD;2BACiB,0BAA0B;mBAClC;+BAGT,eACT,QAAQ"}
1
+ {"version":3,"file":"recorder.d.ts","names":[],"sources":["../src/recorder.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;UA0OiB,qBAAA;;;QAGT;;UAGS,YAAA;;;;;;;;;;;;;;;;;;mCAkBkB,oCAAoC;;;;;;;;;;;;;;;;;;;;;;KAuB3D,YAAA;;;;;;;;;;;;;;;iBA8OU,cAAA,MACf,MAAA,CAAK,sBACL,MAAA,CAAK,yBACD,oCACI,+CAEH;WAEC;UACD;2BACiB,0BAA0B;mBAClC;+BAGT,eACT,QAAQ"}
package/dist/recorder.js CHANGED
@@ -1,9 +1,12 @@
1
+ import { renderError } from "./response/errors.js";
1
2
  import { DEFAULT_TEST_ID } from "./constants.js";
2
3
  import { normalizeModelName } from "./model-utils.js";
3
4
  import { isAuthenticatedRequest, isRecognizedApiKeyHeader } from "./api-key-auth.js";
4
5
  import { getTestId, hasMintedRequestId, slugifyContext, slugifyTestId } from "./helpers.js";
5
6
  import { writeErrorResponse } from "./sse-writer.js";
7
+ import { getEmbeddingRequest } from "./embedding-request.js";
6
8
  import { currentTurnHasToolResult, getLastMessageByRole, getTextContent } from "./router.js";
9
+ import { captureUsage } from "./response/usage/recording.js";
7
10
  import { capturedRedactedData, collapseStreamingResponseWithResponsesTools, withoutResponsesToolFields } from "./stream-collapse.js";
8
11
  import { resolveUpstreamUrl } from "./url.js";
9
12
  import { applyConfiguredProviderAuth, applyProviderAuth } from "./provider-auth.js";
@@ -95,6 +98,7 @@ const STRIP_HEADERS = new Set([
95
98
  "accept-encoding",
96
99
  "x-test-id",
97
100
  "x-aimock-strict",
101
+ "x-aimock-policy",
98
102
  "x-aimock-context"
99
103
  ]);
100
104
  /**
@@ -293,19 +297,19 @@ async function proxyAndRecord(req, res, request, providerKey, pathname, fixtures
293
297
  } catch (err) {
294
298
  const msg = err instanceof Error ? err.message : String(err);
295
299
  defaults.logger.error(`Invalid upstream URL for provider "${providerKey}": ${upstreamUrl} (${msg})`);
296
- writeErrorResponse(res, 502, JSON.stringify({ error: {
300
+ writeErrorResponse(res, 502, renderError("openai", "transport-failure", {
297
301
  message: `Invalid upstream URL: ${upstreamUrl}`,
298
302
  type: "proxy_error"
299
- } }));
303
+ }).body);
300
304
  return "relayed";
301
305
  }
302
306
  defaults.logger.warn(`NO FIXTURE MATCH — proxying to ${upstreamUrl}${pathname}`);
303
307
  const forwardHeaders = prepareEgressHeaders(req, target, providerKey, record.providerKeys?.[lookupKey]);
304
308
  if (!forwardHeaders) {
305
- writeErrorResponse(res, 502, JSON.stringify({ error: {
309
+ writeErrorResponse(res, 502, renderError("openai", "transport-failure", {
306
310
  message: "No configured provider credential",
307
311
  type: "proxy_error"
308
- } }));
312
+ }).body);
309
313
  return "relayed";
310
314
  }
311
315
  const requestBody = rawBody ?? JSON.stringify(request);
@@ -347,10 +351,10 @@ async function proxyAndRecord(req, res, request, providerKey, pathname, fixtures
347
351
  defaults.logger.error(`Proxy request failed: ${msg}`);
348
352
  if (!res.headersSent) {
349
353
  res.writeHead(502, { "Content-Type": "application/json" });
350
- res.end(JSON.stringify({ error: {
354
+ res.end(renderError("openai", "transport-failure", {
351
355
  message: `Proxy to upstream failed: ${msg}`,
352
356
  type: "proxy_error"
353
- } }));
357
+ }).body);
354
358
  } else res.destroy();
355
359
  return "relayed";
356
360
  }
@@ -360,10 +364,10 @@ async function proxyAndRecord(req, res, request, providerKey, pathname, fixtures
360
364
  const ceilingMiB = Math.round(PROXY_BUFFER_HARD_CEILING / (1024 * 1024));
361
365
  defaults.logger.error(`Upstream response exceeded the ${ceilingMiB} MiB proxy hard ceiling (saw ${totalBytes} bytes) on a non-progressive body — cannot relay the full body and refusing to relay a truncated one; returning 502`);
362
366
  res.writeHead(502, { "Content-Type": "application/json" });
363
- res.end(JSON.stringify({ error: {
367
+ res.end(renderError("openai", "transport-failure", {
364
368
  message: `Upstream response exceeds ${ceilingMiB}MiB proxy ceiling`,
365
369
  type: "proxy_error"
366
- } }));
370
+ }).body);
367
371
  return "relayed";
368
372
  }
369
373
  defaults.logger.warn(`Upstream response exceeded ${capDetail} (saw ${totalBytes} bytes) — relayed to client, recording skipped`);
@@ -395,7 +399,14 @@ async function proxyAndRecord(req, res, request, providerKey, pathname, fixtures
395
399
  if (collapsed.truncated) defaults.logger.warn("Bedrock EventStream: CRC mismatch — response may be truncated");
396
400
  if (collapsed.droppedChunks && collapsed.droppedChunks > 0) defaults.logger.warn(`${collapsed.droppedChunks} chunk(s) dropped during stream collapse${collapsed.firstDroppedSample ? ` — first: ${collapsed.firstDroppedSample}` : ""}`);
397
401
  if (collapsed.harmonyUnparsed) defaults.logger.warn(`Harmony tokens present but unparseable — content preserved verbatim${collapsed.harmonyNote ? ` (${collapsed.harmonyNote})` : ""}`);
398
- const collapsedUsage = sanitizeRecordedUsage(collapsed.usage);
402
+ const collapsedUsage = captureUsage({
403
+ provider: providerKey,
404
+ contentType: ctString,
405
+ operation: request._endpointType,
406
+ family: "final",
407
+ stage: "final",
408
+ observation: collapsed.usage
409
+ });
399
410
  const usageSpread = collapsedUsage ? { usage: collapsedUsage } : {};
400
411
  if (collapsed.transcription) fixtureResponse = { transcription: collapsed.transcription };
401
412
  else if (collapsed.audioB64) {
@@ -494,7 +505,7 @@ async function proxyAndRecord(req, res, request, providerKey, pathname, fixtures
494
505
  const msg = parseErr instanceof Error ? parseErr.message : "unknown";
495
506
  defaults.logger.warn(`Upstream response is not valid JSON (${msg}) — saving as error fixture`);
496
507
  }
497
- if ((request._endpointType === "fal" || request._endpointType === "elevenlabs-voice-design" || request._endpointType === "elevenlabs-voice" || request._endpointType === "elevenlabs-voice-get" || request._endpointType === "elevenlabs-voice-delete") && parsedResponse !== null) {
508
+ if ((providerKey === "ollama" && new URL(pathname, "http://localhost").pathname === "/api/embed" || request._endpointType === "fal" || request._endpointType === "elevenlabs-voice-design" || request._endpointType === "elevenlabs-voice" || request._endpointType === "elevenlabs-voice-get" || request._endpointType === "elevenlabs-voice-delete") && parsedResponse !== null) {
498
509
  const obj = parsedResponse;
499
510
  if (typeof obj.error === "object" && obj.error !== null && typeof obj.error.message === "string") {
500
511
  const err = obj.error;
@@ -510,7 +521,11 @@ async function proxyAndRecord(req, res, request, providerKey, pathname, fixtures
510
521
  json: parsedResponse,
511
522
  status: upstreamStatus
512
523
  };
513
- } else fixtureResponse = buildFixtureResponse(parsedResponse, upstreamStatus, defaults.logger, request);
524
+ } else fixtureResponse = buildFixtureResponse(parsedResponse, upstreamStatus, defaults.logger, request, {
525
+ provider: providerKey,
526
+ contentType: ctString,
527
+ operation: request._endpointType
528
+ });
514
529
  }
515
530
  if (clientDisconnected) {
516
531
  if (!sawDone) {
@@ -530,8 +545,15 @@ async function proxyAndRecord(req, res, request, providerKey, pathname, fixtures
530
545
  }
531
546
  const matchRequest = defaults.requestTransform ? defaults.requestTransform(request) : request;
532
547
  const metadata = buildFixtureMetadata(request);
548
+ const embeddingRequest = getEmbeddingRequest(request);
533
549
  const fixture = {
534
- match: buildFixtureMatch(matchRequest, defaults.record),
550
+ match: {
551
+ ...buildFixtureMatch(matchRequest, defaults.record),
552
+ ...embeddingRequest && {
553
+ embeddingRequest: structuredClone(embeddingRequest),
554
+ ...matchRequest.model !== void 0 && { model: matchRequest.model }
555
+ }
556
+ },
535
557
  response: fixtureResponse,
536
558
  ...recordedTimings && { recordedTimings },
537
559
  ...metadata && { metadata }
@@ -841,67 +863,10 @@ function toToolCallArguments(raw) {
841
863
  return JSON.stringify(raw);
842
864
  }
843
865
  /**
844
- * `usage` sub-objects that carry numeric breakdowns rather than a scalar. The
845
- * inner fields are NOT allowlisted here on purpose: the recorder keeps every
846
- * finite-numeric inner field (documented or forward-compat), matching the
847
- * load-time validator in fixture-loader.ts, whose index-signature escape hatch
848
- * accepts undocumented numeric inner keys too. A `Set` (own-key membership via
849
- * `.has()`, no prototype-chain walk) mirrors that validator's
850
- * `new Set(Object.keys(...))` classification so anything this recorder writes
851
- * loads cleanly.
852
- */
853
- const USAGE_OBJECT_FIELDS = new Set([
854
- "cost_details",
855
- "prompt_tokens_details",
856
- "completion_tokens_details"
857
- ]);
858
- /**
859
- * Sanitize a provider-reported `usage` object into the fixture
860
- * `response.usage` override shape (#368).
861
- *
862
- * The recorder persists real upstream usage so replay can serve the provider's
863
- * ACTUAL token counts (instead of the `ceil(len/4)` estimate) and OpenRouter's
864
- * `cost` — which previously never survived recording at all. Upstream usage is
865
- * provider-specific and forward-extending, so this passes fields through rather
866
- * than whitelisting them, but only in the shapes the fixture contract accepts:
867
- *
868
- * - numeric scalars (`prompt_tokens`, `cost`, `native_tokens_prompt`, …) — kept
869
- * - `is_byok` boolean — kept
870
- * - the documented breakdown objects — kept, with non-numeric inner fields
871
- * dropped (the load-time validator rejects those, and a fixture the recorder
872
- * writes must always load)
873
- * - anything else (strings, arrays, nulls, unknown objects) — DROPPED, because
874
- * `fixture-loader.ts` errors on a non-numeric extra `usage` key and a recorded
875
- * fixture that fails validation is worse than one missing an exotic field
876
- *
877
- * Returns `undefined` when nothing survives, so the caller omits `usage`
878
- * entirely and keeps pre-#368 fixtures byte-identical.
879
- */
880
- function sanitizeRecordedUsage(raw) {
881
- if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return void 0;
882
- const out = {};
883
- for (const [key, val] of Object.entries(raw)) {
884
- if (val === void 0 || val === null) continue;
885
- if (USAGE_OBJECT_FIELDS.has(key)) {
886
- if (typeof val !== "object" || val === null || Array.isArray(val)) continue;
887
- const inner = {};
888
- for (const [innerKey, innerVal] of Object.entries(val)) if (typeof innerVal === "number" && Number.isFinite(innerVal)) inner[innerKey] = innerVal;
889
- if (Object.keys(inner).length > 0) out[key] = inner;
890
- continue;
891
- }
892
- if (key === "is_byok") {
893
- if (typeof val === "boolean") out[key] = val;
894
- continue;
895
- }
896
- if (typeof val === "number" && Number.isFinite(val)) out[key] = val;
897
- }
898
- return Object.keys(out).length > 0 ? out : void 0;
899
- }
900
- /**
901
866
  * Detect the response format from the parsed upstream JSON and convert
902
867
  * it into an aimock FixtureResponse.
903
868
  */
904
- function buildFixtureResponse(parsed, status, logger, request) {
869
+ function buildFixtureResponse(parsed, status, logger, request, captureContext = {}) {
905
870
  if (parsed === null || parsed === void 0) return {
906
871
  error: {
907
872
  message: "Upstream returned non-JSON response",
@@ -955,16 +920,32 @@ function buildFixtureResponse(parsed, status, logger, request) {
955
920
  return { images };
956
921
  }
957
922
  const isTranscriptionRequest = request?._endpointType === "transcription" || request?._endpointType === "translation";
958
- if (typeof obj.text === "string" && (isTranscriptionRequest || obj.task === "transcribe" || obj.language !== void 0 && obj.duration !== void 0) && !("choices" in obj) && !("candidates" in obj) && !("object" in obj) && !("message" in obj) && !("outputs" in obj)) return { transcription: {
959
- text: obj.text,
960
- ...obj.language ? { language: String(obj.language) } : {},
961
- ...Array.isArray(obj.languages) ? { languages: obj.languages.filter((language) => typeof language === "object" && language !== null && typeof language.code === "string").map((language) => ({ code: language.code })) } : {},
962
- ...obj.duration !== void 0 ? { duration: Number(obj.duration) } : {},
963
- ...obj.usage && typeof obj.usage === "object" ? { usage: obj.usage } : {},
964
- ...Array.isArray(obj.words) ? { words: obj.words } : {},
965
- ...Array.isArray(obj.segments) ? { segments: obj.segments } : {}
966
- } };
923
+ if (typeof obj.text === "string" && (isTranscriptionRequest || obj.task === "transcribe" || obj.language !== void 0 && obj.duration !== void 0) && !("choices" in obj) && !("candidates" in obj) && !("object" in obj) && !("message" in obj) && !("outputs" in obj)) {
924
+ const transcriptionUsage = captureUsage({
925
+ ...captureContext,
926
+ family: "transcription",
927
+ stage: "nonstream",
928
+ observation: obj
929
+ });
930
+ const transcriptionUsageSpread = transcriptionUsage ? { usage: transcriptionUsage } : {};
931
+ return { transcription: {
932
+ text: obj.text,
933
+ ...obj.language ? { language: String(obj.language) } : {},
934
+ ...Array.isArray(obj.languages) ? { languages: obj.languages.filter((language) => typeof language === "object" && language !== null && typeof language.code === "string").map((language) => ({ code: language.code })) } : {},
935
+ ...obj.duration !== void 0 ? { duration: Number(obj.duration) } : {},
936
+ ...transcriptionUsageSpread,
937
+ ...Array.isArray(obj.words) ? { words: obj.words } : {},
938
+ ...Array.isArray(obj.segments) ? { segments: obj.segments } : {}
939
+ } };
940
+ }
967
941
  if (Array.isArray(obj.outputs) && obj.outputs.length > 0 && !("choices" in obj) && !("content" in obj) && !("candidates" in obj)) {
942
+ const capturedUsage = captureUsage({
943
+ ...captureContext,
944
+ family: "interactions",
945
+ stage: "nonstream",
946
+ observation: obj
947
+ });
948
+ const usageSpread = capturedUsage ? { usage: capturedUsage } : {};
968
949
  const outputs = obj.outputs;
969
950
  const fnCallOutputs = outputs.filter((o) => o.type === "function_call");
970
951
  const textOutputs = outputs.filter((o) => o.type === "text" && typeof o.text === "string");
@@ -978,13 +959,23 @@ function buildFixtureResponse(parsed, status, logger, request) {
978
959
  ...o.id ? { id: String(o.id) } : {}
979
960
  }));
980
961
  if (hasContent) return {
962
+ ...usageSpread,
981
963
  content: joinedText,
982
964
  toolCalls
983
965
  };
984
- return { toolCalls };
966
+ return {
967
+ ...usageSpread,
968
+ toolCalls
969
+ };
985
970
  }
986
- if (hasContent) return { content: joinedText };
987
- return { content: "" };
971
+ if (hasContent) return {
972
+ ...usageSpread,
973
+ content: joinedText
974
+ };
975
+ return {
976
+ ...usageSpread,
977
+ content: ""
978
+ };
988
979
  }
989
980
  if (typeof obj.id === "string" && typeof obj.status === "string" && (obj.status === "completed" || obj.status === "in_progress" || obj.status === "failed") && !("choices" in obj) && !("content" in obj) && !("candidates" in obj) && !("message" in obj) && !("data" in obj) && !("object" in obj) && !("outputs" in obj) && !("model" in obj) && !("response" in obj) && !("done" in obj) && !("usage" in obj) && !("error" in obj)) {
990
981
  if (obj.status === "completed" && obj.url) return { video: {
@@ -1004,7 +995,12 @@ function buildFixtureResponse(parsed, status, logger, request) {
1004
995
  const hasToolCalls = Array.isArray(message.tool_calls) && message.tool_calls.length > 0;
1005
996
  const hasContent = typeof message.content === "string" && message.content.length > 0;
1006
997
  const openaiReasoning = typeof message.reasoning_content === "string" && message.reasoning_content.length > 0 ? message.reasoning_content : typeof message.reasoning === "string" && message.reasoning.length > 0 ? message.reasoning : void 0;
1007
- const openaiUsage = sanitizeRecordedUsage(obj.usage);
998
+ const openaiUsage = captureUsage({
999
+ ...captureContext,
1000
+ family: "openai",
1001
+ stage: "nonstream",
1002
+ observation: obj
1003
+ });
1008
1004
  const usageSpread = openaiUsage ? { usage: openaiUsage } : {};
1009
1005
  if (hasToolCalls) {
1010
1006
  const toolCalls = message.tool_calls.map((tc) => {
@@ -1040,6 +1036,13 @@ function buildFixtureResponse(parsed, status, logger, request) {
1040
1036
  }
1041
1037
  }
1042
1038
  if (Array.isArray(obj.content) && obj.content.length > 0) {
1039
+ const capturedUsage = captureUsage({
1040
+ ...captureContext,
1041
+ family: "anthropic",
1042
+ stage: "nonstream",
1043
+ observation: obj
1044
+ });
1045
+ const usageSpread = capturedUsage ? { usage: capturedUsage } : {};
1043
1046
  const blocks = obj.content;
1044
1047
  const toolUseBlocks = blocks.filter((b) => b.type === "tool_use");
1045
1048
  const textBlocks = blocks.filter((b) => b.type === "text" && typeof b.text === "string");
@@ -1065,6 +1068,7 @@ function buildFixtureResponse(parsed, status, logger, request) {
1065
1068
  ...b.id ? { id: String(b.id) } : {}
1066
1069
  }));
1067
1070
  if (hasContent) return {
1071
+ ...usageSpread,
1068
1072
  content: joinedText,
1069
1073
  toolCalls,
1070
1074
  ...anthropicReasoning ? { reasoning: anthropicReasoning } : {},
@@ -1072,6 +1076,7 @@ function buildFixtureResponse(parsed, status, logger, request) {
1072
1076
  ...redactedThinkingSpread
1073
1077
  };
1074
1078
  return {
1079
+ ...usageSpread,
1075
1080
  toolCalls,
1076
1081
  ...anthropicReasoning ? { reasoning: anthropicReasoning } : {},
1077
1082
  ...reasoningSignatureSpread,
@@ -1079,12 +1084,14 @@ function buildFixtureResponse(parsed, status, logger, request) {
1079
1084
  };
1080
1085
  }
1081
1086
  if (hasContent) return {
1087
+ ...usageSpread,
1082
1088
  content: joinedText,
1083
1089
  ...anthropicReasoning ? { reasoning: anthropicReasoning } : {},
1084
1090
  ...reasoningSignatureSpread,
1085
1091
  ...redactedThinkingSpread
1086
1092
  };
1087
1093
  if (thinkingBlocks.length > 0 || redactedBlocks.length > 0) return {
1094
+ ...usageSpread,
1088
1095
  content: "",
1089
1096
  ...anthropicReasoning ? { reasoning: anthropicReasoning } : {},
1090
1097
  ...reasoningSignatureSpread,
@@ -1094,6 +1101,13 @@ function buildFixtureResponse(parsed, status, logger, request) {
1094
1101
  if (Array.isArray(obj.candidates) && obj.candidates.length > 0) {
1095
1102
  const content = obj.candidates[0].content;
1096
1103
  if (content && Array.isArray(content.parts)) {
1104
+ const capturedUsage = captureUsage({
1105
+ ...captureContext,
1106
+ family: "gemini",
1107
+ stage: "nonstream",
1108
+ observation: obj
1109
+ });
1110
+ const usageSpread = capturedUsage ? { usage: capturedUsage } : {};
1097
1111
  const parts = content.parts;
1098
1112
  const audioParts = parts.filter((p) => {
1099
1113
  const inline = p.inlineData;
@@ -1104,10 +1118,13 @@ function buildFixtureResponse(parsed, status, logger, request) {
1104
1118
  });
1105
1119
  if (audioParts.length > 0) {
1106
1120
  const inlineData = audioParts[0].inlineData;
1107
- return { audio: {
1108
- b64Json: String(inlineData.data ?? ""),
1109
- contentType: typeof inlineData.mimeType === "string" && inlineData.mimeType.length > 0 ? inlineData.mimeType : "audio/mpeg"
1110
- } };
1121
+ return {
1122
+ ...usageSpread,
1123
+ audio: {
1124
+ b64Json: String(inlineData.data ?? ""),
1125
+ contentType: typeof inlineData.mimeType === "string" && inlineData.mimeType.length > 0 ? inlineData.mimeType : "audio/mpeg"
1126
+ }
1127
+ };
1111
1128
  }
1112
1129
  const fnCallParts = parts.filter((p) => p.functionCall);
1113
1130
  const textParts = parts.filter((p) => typeof p.text === "string" && !p.thought);
@@ -1125,20 +1142,24 @@ function buildFixtureResponse(parsed, status, logger, request) {
1125
1142
  };
1126
1143
  });
1127
1144
  if (hasContent) return {
1145
+ ...usageSpread,
1128
1146
  content: joinedText,
1129
1147
  toolCalls,
1130
1148
  ...geminiReasoning ? { reasoning: geminiReasoning } : {}
1131
1149
  };
1132
1150
  return {
1151
+ ...usageSpread,
1133
1152
  toolCalls,
1134
1153
  ...geminiReasoning ? { reasoning: geminiReasoning } : {}
1135
1154
  };
1136
1155
  }
1137
1156
  if (hasContent) return {
1157
+ ...usageSpread,
1138
1158
  content: joinedText,
1139
1159
  ...geminiReasoning ? { reasoning: geminiReasoning } : {}
1140
1160
  };
1141
1161
  return {
1162
+ ...usageSpread,
1142
1163
  content: "",
1143
1164
  ...geminiReasoning ? { reasoning: geminiReasoning } : {}
1144
1165
  };
@@ -1147,6 +1168,13 @@ function buildFixtureResponse(parsed, status, logger, request) {
1147
1168
  if (obj.output && typeof obj.output === "object") {
1148
1169
  const msg = obj.output.message;
1149
1170
  if (msg && Array.isArray(msg.content)) {
1171
+ const capturedUsage = captureUsage({
1172
+ ...captureContext,
1173
+ family: "bedrock-converse",
1174
+ stage: "nonstream",
1175
+ observation: obj
1176
+ });
1177
+ const usageSpread = capturedUsage ? { usage: capturedUsage } : {};
1150
1178
  const blocks = msg.content;
1151
1179
  const toolUseBlocks = blocks.filter((b) => b.toolUse);
1152
1180
  const textBlocks = blocks.filter((b) => typeof b.text === "string");
@@ -1168,26 +1196,37 @@ function buildFixtureResponse(parsed, status, logger, request) {
1168
1196
  };
1169
1197
  });
1170
1198
  if (hasContent) return {
1199
+ ...usageSpread,
1171
1200
  content: joinedText,
1172
1201
  toolCalls,
1173
1202
  ...bedrockReasoning ? { reasoning: bedrockReasoning } : {}
1174
1203
  };
1175
1204
  return {
1205
+ ...usageSpread,
1176
1206
  toolCalls,
1177
1207
  ...bedrockReasoning ? { reasoning: bedrockReasoning } : {}
1178
1208
  };
1179
1209
  }
1180
1210
  if (hasContent) return {
1211
+ ...usageSpread,
1181
1212
  content: joinedText,
1182
1213
  ...bedrockReasoning ? { reasoning: bedrockReasoning } : {}
1183
1214
  };
1184
1215
  return {
1216
+ ...usageSpread,
1185
1217
  content: "",
1186
1218
  ...bedrockReasoning ? { reasoning: bedrockReasoning } : {}
1187
1219
  };
1188
1220
  }
1189
1221
  }
1190
1222
  if (typeof obj.finish_reason === "string" && obj.message && typeof obj.message === "object" && Array.isArray(obj.message.content)) {
1223
+ const capturedUsage = captureUsage({
1224
+ ...captureContext,
1225
+ family: "cohere",
1226
+ stage: "nonstream",
1227
+ observation: obj
1228
+ });
1229
+ const usageSpread = capturedUsage ? { usage: capturedUsage } : {};
1191
1230
  const msg = obj.message;
1192
1231
  const contentBlocks = msg.content;
1193
1232
  const joinedText = contentBlocks.filter((b) => b.type === "text" && typeof b.text === "string").map((b) => String(b.text ?? "")).join("");
@@ -1201,10 +1240,14 @@ function buildFixtureResponse(parsed, status, logger, request) {
1201
1240
  ...b.id ? { id: String(b.id) } : {}
1202
1241
  }));
1203
1242
  if (hasContent) return {
1243
+ ...usageSpread,
1204
1244
  content: joinedText,
1205
1245
  toolCalls
1206
1246
  };
1207
- return { toolCalls };
1247
+ return {
1248
+ ...usageSpread,
1249
+ toolCalls
1250
+ };
1208
1251
  }
1209
1252
  if (msgToolCalls.length > 0) {
1210
1253
  const toolCalls = msgToolCalls.map((tc) => {
@@ -1216,15 +1259,32 @@ function buildFixtureResponse(parsed, status, logger, request) {
1216
1259
  };
1217
1260
  });
1218
1261
  if (hasContent) return {
1262
+ ...usageSpread,
1219
1263
  content: joinedText,
1220
1264
  toolCalls
1221
1265
  };
1222
- return { toolCalls };
1266
+ return {
1267
+ ...usageSpread,
1268
+ toolCalls
1269
+ };
1223
1270
  }
1224
- if (hasContent) return { content: joinedText };
1225
- return { content: "" };
1271
+ if (hasContent) return {
1272
+ ...usageSpread,
1273
+ content: joinedText
1274
+ };
1275
+ return {
1276
+ ...usageSpread,
1277
+ content: ""
1278
+ };
1226
1279
  }
1227
1280
  if (obj.message && typeof obj.message === "object") {
1281
+ const capturedUsage = captureUsage({
1282
+ ...captureContext,
1283
+ family: "ollama",
1284
+ stage: "nonstream",
1285
+ observation: obj
1286
+ });
1287
+ const usageSpread = capturedUsage ? { usage: capturedUsage } : {};
1228
1288
  const msg = obj.message;
1229
1289
  const hasOllamaToolCalls = Array.isArray(msg.tool_calls) && msg.tool_calls.length > 0;
1230
1290
  const hasOllamaContent = typeof msg.content === "string" && msg.content.length > 0;
@@ -1237,18 +1297,39 @@ function buildFixtureResponse(parsed, status, logger, request) {
1237
1297
  };
1238
1298
  });
1239
1299
  if (hasOllamaContent) return {
1300
+ ...usageSpread,
1240
1301
  content: msg.content,
1241
1302
  toolCalls
1242
1303
  };
1243
- return { toolCalls };
1304
+ return {
1305
+ ...usageSpread,
1306
+ toolCalls
1307
+ };
1244
1308
  }
1245
- if (hasOllamaContent) return { content: msg.content };
1309
+ if (hasOllamaContent) return {
1310
+ ...usageSpread,
1311
+ content: msg.content
1312
+ };
1246
1313
  if (Array.isArray(msg.content) && msg.content.length > 0) {
1247
1314
  const first = msg.content[0];
1248
- if (typeof first.text === "string") return { content: first.text };
1315
+ if (typeof first.text === "string") return {
1316
+ ...usageSpread,
1317
+ content: first.text
1318
+ };
1249
1319
  }
1250
1320
  }
1251
- if (typeof obj.response === "string" && typeof obj.done === "boolean") return { content: obj.response };
1321
+ if (typeof obj.response === "string" && typeof obj.done === "boolean") {
1322
+ const capturedUsage = captureUsage({
1323
+ ...captureContext,
1324
+ family: "ollama",
1325
+ stage: "nonstream",
1326
+ observation: obj
1327
+ });
1328
+ return {
1329
+ ...capturedUsage ? { usage: capturedUsage } : {},
1330
+ content: obj.response
1331
+ };
1332
+ }
1252
1333
  logger?.warn(`Could not detect response format from upstream (status=${status}) — saving as error fixture; top-level keys: [${Object.keys(obj).join(", ")}]`);
1253
1334
  return {
1254
1335
  error: {