@copilotkit/aimock 1.45.0 → 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 (426) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +24 -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.ts.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-fakes.d.cts.map +1 -1
  177. package/dist/mcp-handler.cjs +14 -4
  178. package/dist/mcp-handler.cjs.map +1 -1
  179. package/dist/mcp-handler.js +14 -4
  180. package/dist/mcp-handler.js.map +1 -1
  181. package/dist/mcp-recorder.cjs +2 -1
  182. package/dist/mcp-recorder.cjs.map +1 -1
  183. package/dist/mcp-recorder.js +3 -2
  184. package/dist/mcp-recorder.js.map +1 -1
  185. package/dist/messages.cjs +111 -96
  186. package/dist/messages.cjs.map +1 -1
  187. package/dist/messages.d.cts.map +1 -1
  188. package/dist/messages.d.ts.map +1 -1
  189. package/dist/messages.js +109 -95
  190. package/dist/messages.js.map +1 -1
  191. package/dist/metrics.cjs +5 -2
  192. package/dist/metrics.cjs.map +1 -1
  193. package/dist/metrics.d.cts.map +1 -1
  194. package/dist/metrics.d.ts.map +1 -1
  195. package/dist/metrics.js +6 -3
  196. package/dist/metrics.js.map +1 -1
  197. package/dist/model-utils.cjs +1 -0
  198. package/dist/model-utils.cjs.map +1 -1
  199. package/dist/model-utils.js +1 -1
  200. package/dist/model-utils.js.map +1 -1
  201. package/dist/moderation.cjs +15 -12
  202. package/dist/moderation.cjs.map +1 -1
  203. package/dist/moderation.js +14 -11
  204. package/dist/moderation.js.map +1 -1
  205. package/dist/ollama.cjs +128 -68
  206. package/dist/ollama.cjs.map +1 -1
  207. package/dist/ollama.d.cts.map +1 -1
  208. package/dist/ollama.d.ts.map +1 -1
  209. package/dist/ollama.js +124 -64
  210. package/dist/ollama.js.map +1 -1
  211. package/dist/openapi.cjs +323 -3
  212. package/dist/openapi.cjs.map +1 -1
  213. package/dist/openapi.d.cts.map +1 -1
  214. package/dist/openapi.d.ts.map +1 -1
  215. package/dist/openapi.js +324 -4
  216. package/dist/openapi.js.map +1 -1
  217. package/dist/openrouter-chat.cjs +11 -155
  218. package/dist/openrouter-chat.cjs.map +1 -1
  219. package/dist/openrouter-chat.js +11 -155
  220. package/dist/openrouter-chat.js.map +1 -1
  221. package/dist/openrouter-video.cjs +76 -71
  222. package/dist/openrouter-video.cjs.map +1 -1
  223. package/dist/openrouter-video.d.cts.map +1 -1
  224. package/dist/openrouter-video.d.ts.map +1 -1
  225. package/dist/openrouter-video.js +63 -58
  226. package/dist/openrouter-video.js.map +1 -1
  227. package/dist/recorder.cjs +176 -95
  228. package/dist/recorder.cjs.map +1 -1
  229. package/dist/recorder.d.cts.map +1 -1
  230. package/dist/recorder.d.ts.map +1 -1
  231. package/dist/recorder.js +176 -95
  232. package/dist/recorder.js.map +1 -1
  233. package/dist/rerank.cjs +13 -11
  234. package/dist/rerank.cjs.map +1 -1
  235. package/dist/rerank.js +12 -10
  236. package/dist/rerank.js.map +1 -1
  237. package/dist/response/catalog/anthropic-page.cjs +39 -0
  238. package/dist/response/catalog/anthropic-page.cjs.map +1 -0
  239. package/dist/response/catalog/anthropic-page.js +38 -0
  240. package/dist/response/catalog/anthropic-page.js.map +1 -0
  241. package/dist/response/catalog/collect.cjs +61 -0
  242. package/dist/response/catalog/collect.cjs.map +1 -0
  243. package/dist/response/catalog/collect.js +59 -0
  244. package/dist/response/catalog/collect.js.map +1 -0
  245. package/dist/response/catalog/gemini-page.cjs +25 -0
  246. package/dist/response/catalog/gemini-page.cjs.map +1 -0
  247. package/dist/response/catalog/gemini-page.js +24 -0
  248. package/dist/response/catalog/gemini-page.js.map +1 -0
  249. package/dist/response/catalog/render.cjs +182 -0
  250. package/dist/response/catalog/render.cjs.map +1 -0
  251. package/dist/response/catalog/render.js +171 -0
  252. package/dist/response/catalog/render.js.map +1 -0
  253. package/dist/response/errors.cjs +225 -0
  254. package/dist/response/errors.cjs.map +1 -0
  255. package/dist/response/errors.js +224 -0
  256. package/dist/response/errors.js.map +1 -0
  257. package/dist/response/finish.cjs +39 -0
  258. package/dist/response/finish.cjs.map +1 -0
  259. package/dist/response/finish.js +35 -0
  260. package/dist/response/finish.js.map +1 -0
  261. package/dist/response/policy.cjs +126 -0
  262. package/dist/response/policy.cjs.map +1 -0
  263. package/dist/response/policy.js +120 -0
  264. package/dist/response/policy.js.map +1 -0
  265. package/dist/response/profiles.cjs +69 -0
  266. package/dist/response/profiles.cjs.map +1 -0
  267. package/dist/response/profiles.js +65 -0
  268. package/dist/response/profiles.js.map +1 -0
  269. package/dist/response/usage/codecs/anthropic.cjs +52 -0
  270. package/dist/response/usage/codecs/anthropic.cjs.map +1 -0
  271. package/dist/response/usage/codecs/anthropic.js +50 -0
  272. package/dist/response/usage/codecs/anthropic.js.map +1 -0
  273. package/dist/response/usage/codecs/cohere.cjs +36 -0
  274. package/dist/response/usage/codecs/cohere.cjs.map +1 -0
  275. package/dist/response/usage/codecs/cohere.js +35 -0
  276. package/dist/response/usage/codecs/cohere.js.map +1 -0
  277. package/dist/response/usage/codecs/converse.cjs +16 -0
  278. package/dist/response/usage/codecs/converse.cjs.map +1 -0
  279. package/dist/response/usage/codecs/converse.js +15 -0
  280. package/dist/response/usage/codecs/converse.js.map +1 -0
  281. package/dist/response/usage/codecs/gemini.cjs +31 -0
  282. package/dist/response/usage/codecs/gemini.cjs.map +1 -0
  283. package/dist/response/usage/codecs/gemini.js +31 -0
  284. package/dist/response/usage/codecs/gemini.js.map +1 -0
  285. package/dist/response/usage/codecs/interactions.cjs +22 -0
  286. package/dist/response/usage/codecs/interactions.cjs.map +1 -0
  287. package/dist/response/usage/codecs/interactions.js +21 -0
  288. package/dist/response/usage/codecs/interactions.js.map +1 -0
  289. package/dist/response/usage/codecs/ollama.cjs +17 -0
  290. package/dist/response/usage/codecs/ollama.cjs.map +1 -0
  291. package/dist/response/usage/codecs/ollama.js +17 -0
  292. package/dist/response/usage/codecs/ollama.js.map +1 -0
  293. package/dist/response/usage/codecs/openai.cjs +52 -0
  294. package/dist/response/usage/codecs/openai.cjs.map +1 -0
  295. package/dist/response/usage/codecs/openai.js +50 -0
  296. package/dist/response/usage/codecs/openai.js.map +1 -0
  297. package/dist/response/usage/codecs/openrouter.cjs +68 -0
  298. package/dist/response/usage/codecs/openrouter.cjs.map +1 -0
  299. package/dist/response/usage/codecs/openrouter.js +67 -0
  300. package/dist/response/usage/codecs/openrouter.js.map +1 -0
  301. package/dist/response/usage/codecs/realtime.cjs +19 -0
  302. package/dist/response/usage/codecs/realtime.cjs.map +1 -0
  303. package/dist/response/usage/codecs/realtime.js +18 -0
  304. package/dist/response/usage/codecs/realtime.js.map +1 -0
  305. package/dist/response/usage/codecs/responses.cjs +21 -0
  306. package/dist/response/usage/codecs/responses.cjs.map +1 -0
  307. package/dist/response/usage/codecs/responses.js +20 -0
  308. package/dist/response/usage/codecs/responses.js.map +1 -0
  309. package/dist/response/usage/estimate.cjs +23 -0
  310. package/dist/response/usage/estimate.cjs.map +1 -0
  311. package/dist/response/usage/estimate.js +21 -0
  312. package/dist/response/usage/estimate.js.map +1 -0
  313. package/dist/response/usage/fields.cjs +72 -0
  314. package/dist/response/usage/fields.cjs.map +1 -0
  315. package/dist/response/usage/fields.js +70 -0
  316. package/dist/response/usage/fields.js.map +1 -0
  317. package/dist/response/usage/recording.cjs +52 -0
  318. package/dist/response/usage/recording.cjs.map +1 -0
  319. package/dist/response/usage/recording.js +52 -0
  320. package/dist/response/usage/recording.js.map +1 -0
  321. package/dist/responses.cjs +45 -58
  322. package/dist/responses.cjs.map +1 -1
  323. package/dist/responses.d.cts.map +1 -1
  324. package/dist/responses.d.ts.map +1 -1
  325. package/dist/responses.js +44 -57
  326. package/dist/responses.js.map +1 -1
  327. package/dist/route-registry.cjs +45 -0
  328. package/dist/route-registry.cjs.map +1 -1
  329. package/dist/route-registry.d.cts.map +1 -1
  330. package/dist/route-registry.d.ts.map +1 -1
  331. package/dist/route-registry.js +41 -1
  332. package/dist/route-registry.js.map +1 -1
  333. package/dist/router.cjs +4 -0
  334. package/dist/router.cjs.map +1 -1
  335. package/dist/router.d.cts.map +1 -1
  336. package/dist/router.d.ts.map +1 -1
  337. package/dist/router.js +3 -0
  338. package/dist/router.js.map +1 -1
  339. package/dist/search.cjs +13 -11
  340. package/dist/search.cjs.map +1 -1
  341. package/dist/search.js +12 -10
  342. package/dist/search.js.map +1 -1
  343. package/dist/server.cjs +222 -146
  344. package/dist/server.cjs.map +1 -1
  345. package/dist/server.d.cts.map +1 -1
  346. package/dist/server.d.ts.map +1 -1
  347. package/dist/server.js +223 -147
  348. package/dist/server.js.map +1 -1
  349. package/dist/speech.cjs +20 -18
  350. package/dist/speech.cjs.map +1 -1
  351. package/dist/speech.d.cts.map +1 -1
  352. package/dist/speech.d.ts.map +1 -1
  353. package/dist/speech.js +19 -17
  354. package/dist/speech.js.map +1 -1
  355. package/dist/sse-writer.cjs +7 -0
  356. package/dist/sse-writer.cjs.map +1 -1
  357. package/dist/sse-writer.d.cts.map +1 -1
  358. package/dist/sse-writer.d.ts.map +1 -1
  359. package/dist/sse-writer.js +7 -1
  360. package/dist/sse-writer.js.map +1 -1
  361. package/dist/stream-collapse.cjs +118 -11
  362. package/dist/stream-collapse.cjs.map +1 -1
  363. package/dist/stream-collapse.d.cts +10 -9
  364. package/dist/stream-collapse.d.cts.map +1 -1
  365. package/dist/stream-collapse.d.ts +10 -9
  366. package/dist/stream-collapse.d.ts.map +1 -1
  367. package/dist/stream-collapse.js +118 -11
  368. package/dist/stream-collapse.js.map +1 -1
  369. package/dist/transcription.cjs +12 -10
  370. package/dist/transcription.cjs.map +1 -1
  371. package/dist/transcription.d.cts.map +1 -1
  372. package/dist/transcription.d.ts.map +1 -1
  373. package/dist/transcription.js +11 -9
  374. package/dist/transcription.js.map +1 -1
  375. package/dist/types.cjs.map +1 -1
  376. package/dist/types.d.cts +62 -3
  377. package/dist/types.d.cts.map +1 -1
  378. package/dist/types.d.ts +62 -3
  379. package/dist/types.d.ts.map +1 -1
  380. package/dist/types.js.map +1 -1
  381. package/dist/vector-mock.cjs +3 -8
  382. package/dist/vector-mock.cjs.map +1 -1
  383. package/dist/vector-mock.d.cts.map +1 -1
  384. package/dist/vector-mock.d.ts.map +1 -1
  385. package/dist/vector-mock.js +3 -8
  386. package/dist/vector-mock.js.map +1 -1
  387. package/dist/vector-stores.cjs +2 -4
  388. package/dist/vector-stores.cjs.map +1 -1
  389. package/dist/vector-stores.d.cts.map +1 -1
  390. package/dist/vector-stores.d.ts.map +1 -1
  391. package/dist/vector-stores.js +2 -4
  392. package/dist/vector-stores.js.map +1 -1
  393. package/dist/veo-video.cjs +16 -14
  394. package/dist/veo-video.cjs.map +1 -1
  395. package/dist/veo-video.js +10 -8
  396. package/dist/veo-video.js.map +1 -1
  397. package/dist/video.cjs +21 -19
  398. package/dist/video.cjs.map +1 -1
  399. package/dist/video.d.cts.map +1 -1
  400. package/dist/video.d.ts.map +1 -1
  401. package/dist/video.js +20 -18
  402. package/dist/video.js.map +1 -1
  403. package/dist/ws-gemini-live.cjs +11 -3
  404. package/dist/ws-gemini-live.cjs.map +1 -1
  405. package/dist/ws-gemini-live.d.cts +0 -1
  406. package/dist/ws-gemini-live.d.cts.map +1 -1
  407. package/dist/ws-gemini-live.d.ts +0 -1
  408. package/dist/ws-gemini-live.d.ts.map +1 -1
  409. package/dist/ws-gemini-live.js +10 -2
  410. package/dist/ws-gemini-live.js.map +1 -1
  411. package/dist/ws-live.cjs +6 -5
  412. package/dist/ws-live.cjs.map +1 -1
  413. package/dist/ws-live.js +5 -4
  414. package/dist/ws-live.js.map +1 -1
  415. package/dist/ws-realtime.cjs +28 -54
  416. package/dist/ws-realtime.cjs.map +1 -1
  417. package/dist/ws-realtime.d.cts.map +1 -1
  418. package/dist/ws-realtime.d.ts.map +1 -1
  419. package/dist/ws-realtime.js +25 -51
  420. package/dist/ws-realtime.js.map +1 -1
  421. package/dist/ws-responses.cjs +8 -6
  422. package/dist/ws-responses.cjs.map +1 -1
  423. package/dist/ws-responses.js +7 -5
  424. package/dist/ws-responses.js.map +1 -1
  425. package/package.json +4 -1
  426. package/skills/write-fixtures/SKILL.md +25 -16
@@ -56,15 +56,12 @@ interface CollapseResult {
56
56
  redactedThinking?: string[];
57
57
  webSearches?: string[];
58
58
  /**
59
- * The provider-reported `usage` object from the stream's final usage frame,
60
- * captured VERBATIM (#368). OpenAI-compatible streams (including OpenRouter)
61
- * close with a `chat.completion.chunk` whose `choices` is empty and whose
62
- * `usage` carries the real token counts — plus, on OpenRouter,
63
- * `cost` / `cost_details` / `native_tokens_*`. Collapsing dropped that frame,
64
- * so a recorded fixture could only ever replay estimated (`ceil(len/4)`) token
65
- * counts and never a provider-reported cost. Last-usage-wins: a stream that
66
- * emits several usage frames keeps the final one. Absent when the upstream
67
- * stream carried no usage (e.g. `stream_options.include_usage` unset).
59
+ * Provider-reported usage captured with each wire's merge rule. OpenAI and
60
+ * OpenRouter preserve the last nonempty usage object, including cost fields.
61
+ * Anthropic Messages and Bedrock Claude invoke merge message_start usage
62
+ * with numeric message_delta updates; null keeps the earlier count. Cache
63
+ * TTL objects come from message_start. Other wire families omit usage.
64
+ * Absent when no usage was captured from the upstream stream.
68
65
  *
69
66
  * Kept as a loose record because the field set is provider-specific and
70
67
  * forward-extending; the recorder sanitizes it into the fixture
@@ -154,6 +151,8 @@ declare function collapseOpenAISSE(rawBody: string): CollapseResult;
154
151
 
155
152
  /**
156
153
  * Collapse Anthropic Claude Messages SSE stream into a single response.
154
+ * Captures start usage and numeric delta updates; null keeps the start value.
155
+ * Cache TTL objects are captured from message_start, alongside flat counts.
157
156
  *
158
157
  * Format:
159
158
  * event: message_start\ndata: {...}\n\n
@@ -191,6 +190,8 @@ declare function collapseOllamaNDJSON(rawBody: string): CollapseResult;
191
190
  declare function collapseCohereSSE(rawBody: string): CollapseResult;
192
191
  /**
193
192
  * Collapse Bedrock binary Event Stream into a single response.
193
+ * Claude invoke events preserve usage with the Anthropic start/delta rules;
194
+ * Converse usage remains omitted.
194
195
  *
195
196
  * Each frame contains a JSON payload with event types like:
196
197
  * contentBlockDelta, contentBlockStart, etc.
@@ -1 +1 @@
1
- {"version":3,"file":"stream-collapse.d.cts","names":[],"sources":["../src/stream-collapse.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;AA+eA;AAsjBA;AAkMA;AAyJA;AAmIA;AA6RA;;;;;AAyTA;AA2LA;;;AAGiB,cA3uEJ,0BA2uEI,EAAA,MAAA;;AAEd,iBAluEa,8BAAA,CAkuEb,KAAA,EAAA,MAAA,GAAA,SAAA,CAAA,EAAA,IAAA;AAAc,UAlrEA,cAAA,CAkrEA;;;;gBA9qED;;;YACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAqCF;;;;;cAKI;;;;;;oBAMM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAoCT;;;;;;;oBAOS;;;;;;;;;;;;;;;;;;;;;;iBAwSJ,iBAAA,mBAAoC;;;;;;;;;;;;;iBAsjBpC,oBAAA,mBAAuC;;;;;;;iBAkMvC,iBAAA,mBAAoC;;;;;;;;;;;;;;;iBAyJpC,oBAAA,mBAAuC;;;;;;;iBAmIvC,iBAAA,mBAAoC;;;;;;;iBA6RpC,0BAAA,UAAoC,SAAS;;;;;;;;;;;;;;;iBAyT7C,6BAAA,mBAAgD;;;;;;;;;iBA2LhD,yBAAA,mCAED,kCACE,iBACN,SACR"}
1
+ {"version":3,"file":"stream-collapse.d.cts","names":[],"sources":["../src/stream-collapse.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;AA6eA;AA0jBA;AA+MA;AAuKA;AAgJA;AA4SA;;;;;AAsUA;AAwMA;;;AAGiB,cA7zEJ,0BA6zEI,EAAA,MAAA;;AAEd,iBApzEa,8BAAA,CAozEb,KAAA,EAAA,MAAA,GAAA,SAAA,CAAA,EAAA,IAAA;AAAc,UApwEA,cAAA,CAowEA;;;;gBAhwED;;;YACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAkCF;;;;;cAKI;;;;;;oBAMM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAoCT;;;;;;;oBAOS;;;;;;;;;;;;;;;;;;;;;;iBAwSJ,iBAAA,mBAAoC;;;;;;;;;;;;;;;iBA0jBpC,oBAAA,mBAAuC;;;;;;;iBA+MvC,iBAAA,mBAAoC;;;;;;;;;;;;;;;iBAuKpC,oBAAA,mBAAuC;;;;;;;iBAgJvC,iBAAA,mBAAoC;;;;;;;;;iBA4SpC,0BAAA,UAAoC,SAAS;;;;;;;;;;;;;;;iBAsU7C,6BAAA,mBAAgD;;;;;;;;;iBAwMhD,yBAAA,mCAED,kCACE,iBACN,SACR"}
@@ -56,15 +56,12 @@ interface CollapseResult {
56
56
  redactedThinking?: string[];
57
57
  webSearches?: string[];
58
58
  /**
59
- * The provider-reported `usage` object from the stream's final usage frame,
60
- * captured VERBATIM (#368). OpenAI-compatible streams (including OpenRouter)
61
- * close with a `chat.completion.chunk` whose `choices` is empty and whose
62
- * `usage` carries the real token counts — plus, on OpenRouter,
63
- * `cost` / `cost_details` / `native_tokens_*`. Collapsing dropped that frame,
64
- * so a recorded fixture could only ever replay estimated (`ceil(len/4)`) token
65
- * counts and never a provider-reported cost. Last-usage-wins: a stream that
66
- * emits several usage frames keeps the final one. Absent when the upstream
67
- * stream carried no usage (e.g. `stream_options.include_usage` unset).
59
+ * Provider-reported usage captured with each wire's merge rule. OpenAI and
60
+ * OpenRouter preserve the last nonempty usage object, including cost fields.
61
+ * Anthropic Messages and Bedrock Claude invoke merge message_start usage
62
+ * with numeric message_delta updates; null keeps the earlier count. Cache
63
+ * TTL objects come from message_start. Other wire families omit usage.
64
+ * Absent when no usage was captured from the upstream stream.
68
65
  *
69
66
  * Kept as a loose record because the field set is provider-specific and
70
67
  * forward-extending; the recorder sanitizes it into the fixture
@@ -154,6 +151,8 @@ declare function collapseOpenAISSE(rawBody: string): CollapseResult;
154
151
 
155
152
  /**
156
153
  * Collapse Anthropic Claude Messages SSE stream into a single response.
154
+ * Captures start usage and numeric delta updates; null keeps the start value.
155
+ * Cache TTL objects are captured from message_start, alongside flat counts.
157
156
  *
158
157
  * Format:
159
158
  * event: message_start\ndata: {...}\n\n
@@ -191,6 +190,8 @@ declare function collapseOllamaNDJSON(rawBody: string): CollapseResult;
191
190
  declare function collapseCohereSSE(rawBody: string): CollapseResult;
192
191
  /**
193
192
  * Collapse Bedrock binary Event Stream into a single response.
193
+ * Claude invoke events preserve usage with the Anthropic start/delta rules;
194
+ * Converse usage remains omitted.
194
195
  *
195
196
  * Each frame contains a JSON payload with event types like:
196
197
  * contentBlockDelta, contentBlockStart, etc.
@@ -1 +1 @@
1
- {"version":3,"file":"stream-collapse.d.ts","names":[],"sources":["../src/stream-collapse.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;AA+eA;AAsjBA;AAkMA;AAyJA;AAmIA;AA6RA;;;;;AAyTA;AA2LA;;;AAGiB,cA3uEJ,0BA2uEI,EAAA,MAAA;;AAEd,iBAluEa,8BAAA,CAkuEb,KAAA,EAAA,MAAA,GAAA,SAAA,CAAA,EAAA,IAAA;AAAc,UAlrEA,cAAA,CAkrEA;;;;gBA9qED;;;YACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAqCF;;;;;cAKI;;;;;;oBAMM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAoCT;;;;;;;oBAOS;;;;;;;;;;;;;;;;;;;;;;iBAwSJ,iBAAA,mBAAoC;;;;;;;;;;;;;iBAsjBpC,oBAAA,mBAAuC;;;;;;;iBAkMvC,iBAAA,mBAAoC;;;;;;;;;;;;;;;iBAyJpC,oBAAA,mBAAuC;;;;;;;iBAmIvC,iBAAA,mBAAoC;;;;;;;iBA6RpC,0BAAA,UAAoC,SAAS;;;;;;;;;;;;;;;iBAyT7C,6BAAA,mBAAgD;;;;;;;;;iBA2LhD,yBAAA,mCAED,kCACE,iBACN,SACR"}
1
+ {"version":3,"file":"stream-collapse.d.ts","names":[],"sources":["../src/stream-collapse.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;AA6eA;AA0jBA;AA+MA;AAuKA;AAgJA;AA4SA;;;;;AAsUA;AAwMA;;;AAGiB,cA7zEJ,0BA6zEI,EAAA,MAAA;;AAEd,iBApzEa,8BAAA,CAozEb,KAAA,EAAA,MAAA,GAAA,SAAA,CAAA,EAAA,IAAA;AAAc,UApwEA,cAAA,CAowEA;;;;gBAhwED;;;YACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAkCF;;;;;cAKI;;;;;;oBAMM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAoCT;;;;;;;oBAOS;;;;;;;;;;;;;;;;;;;;;;iBAwSJ,iBAAA,mBAAoC;;;;;;;;;;;;;;;iBA0jBpC,oBAAA,mBAAuC;;;;;;;iBA+MvC,iBAAA,mBAAoC;;;;;;;;;;;;;;;iBAuKpC,oBAAA,mBAAuC;;;;;;;iBAgJvC,iBAAA,mBAAoC;;;;;;;;;iBA4SpC,0BAAA,UAAoC,SAAS;;;;;;;;;;;;;;;iBAsU7C,6BAAA,mBAAgD;;;;;;;;;iBAwMhD,yBAAA,mCAED,kCACE,iBACN,SACR"}
@@ -1,3 +1,4 @@
1
+ import { captureUsage } from "./response/usage/recording.js";
1
2
  import { isHarmonyContent, parseHarmonyContent } from "./harmony.js";
2
3
  import { crc32 } from "node:zlib";
3
4
 
@@ -360,7 +361,15 @@ function collapseOpenAISSEWithResponsesTools(rawBody) {
360
361
  transcript = parsed.text;
361
362
  transcriptSeen = true;
362
363
  if (Array.isArray(parsed.languages)) transcriptLanguages = parsed.languages.filter((language) => typeof language === "object" && language !== null && typeof language.code === "string").map((language) => ({ code: language.code }));
363
- if (parsed.usage && typeof parsed.usage === "object" && !Array.isArray(parsed.usage) && Object.keys(parsed.usage).length > 0) transcriptUsage = parsed.usage;
364
+ transcriptUsage = captureUsage({
365
+ provider: "openai",
366
+ contentType: "text/event-stream",
367
+ operation: "transcription",
368
+ family: "transcription",
369
+ stage: "stream",
370
+ previous: transcriptUsage,
371
+ observation: parsed
372
+ });
364
373
  continue;
365
374
  }
366
375
  if (parsed.type === "response.reasoning_summary_text.delta" && typeof parsed.delta === "string") {
@@ -547,7 +556,15 @@ function collapseOpenAISSEWithResponsesTools(rawBody) {
547
556
  continue;
548
557
  }
549
558
  if (typeof parsed.type === "string" && parsed.type.startsWith("response.")) continue;
550
- if (parsed.usage && typeof parsed.usage === "object" && !Array.isArray(parsed.usage) && Object.keys(parsed.usage).length > 0) usage = parsed.usage;
559
+ usage = captureUsage({
560
+ provider: "openai",
561
+ contentType: "text/event-stream",
562
+ operation: "chat",
563
+ family: "openai",
564
+ stage: "stream",
565
+ previous: usage,
566
+ observation: parsed
567
+ });
551
568
  const choices = parsed.choices;
552
569
  if (!choices || choices.length === 0) continue;
553
570
  const delta = choices[0].delta;
@@ -663,6 +680,8 @@ function collapseOpenAISSEWithResponsesTools(rawBody) {
663
680
  }
664
681
  /**
665
682
  * Collapse Anthropic Claude Messages SSE stream into a single response.
683
+ * Captures start usage and numeric delta updates; null keeps the start value.
684
+ * Cache TTL objects are captured from message_start, alongside flat counts.
666
685
  *
667
686
  * Format:
668
687
  * event: message_start\ndata: {...}\n\n
@@ -671,6 +690,7 @@ function collapseOpenAISSEWithResponsesTools(rawBody) {
671
690
  function collapseAnthropicSSE(rawBody) {
672
691
  const inputTruncated = isCollapseInputTruncated(rawBody);
673
692
  const blocks = splitSSEEvents(guardCollapseBody(rawBody));
693
+ let usage;
674
694
  let content = "";
675
695
  let reasoning = "";
676
696
  let reasoningSignature;
@@ -696,6 +716,15 @@ function collapseAnthropicSSE(rawBody) {
696
716
  if (droppedChunks === 1) firstDroppedSample = `parse failed (${err instanceof Error ? err.message : "unknown"}): ${surrogateSafeSlice(payload, 200)}`;
697
717
  continue;
698
718
  }
719
+ usage = captureUsage({
720
+ provider: "anthropic",
721
+ contentType: "text/event-stream",
722
+ operation: "chat",
723
+ family: "anthropic",
724
+ stage: "stream",
725
+ previous: usage,
726
+ observation: parsed
727
+ });
699
728
  if (eventType === "content_block_start") {
700
729
  const contentBlock = parsed.content_block;
701
730
  const redactedData = capturedRedactedData(contentBlock);
@@ -753,6 +782,7 @@ function collapseAnthropicSSE(rawBody) {
753
782
  ...tc.id ? { id: tc.id } : {}
754
783
  }));
755
784
  return {
785
+ ...usage ? { usage } : {},
756
786
  ...orderedBlocks ? { blocks: orderedBlocks } : {},
757
787
  ...content ? { content } : {},
758
788
  toolCalls: orderedBlocks ? orderedToolCalls : indexSortedToolCalls,
@@ -765,6 +795,7 @@ function collapseAnthropicSSE(rawBody) {
765
795
  };
766
796
  }
767
797
  return {
798
+ ...usage ? { usage } : {},
768
799
  content,
769
800
  ...reasoning ? { reasoning } : {},
770
801
  ...reasoningSignature ? { reasoningSignature } : {},
@@ -783,6 +814,7 @@ function collapseAnthropicSSE(rawBody) {
783
814
  function collapseGeminiSSE(rawBody) {
784
815
  const inputTruncated = isCollapseInputTruncated(rawBody);
785
816
  const lines = splitSSEEvents(guardCollapseBody(rawBody));
817
+ let usage;
786
818
  let content = "";
787
819
  let reasoning = "";
788
820
  let droppedChunks = 0;
@@ -803,6 +835,15 @@ function collapseGeminiSSE(rawBody) {
803
835
  if (droppedChunks === 1) firstDroppedSample = `parse failed (${err instanceof Error ? err.message : "unknown"}): ${surrogateSafeSlice(payload, 200)}`;
804
836
  continue;
805
837
  }
838
+ usage = captureUsage({
839
+ provider: "gemini",
840
+ contentType: "text/event-stream",
841
+ operation: "chat",
842
+ family: "gemini",
843
+ stage: "stream",
844
+ previous: usage,
845
+ observation: parsed
846
+ });
806
847
  const candidates = parsed.candidates;
807
848
  if (!candidates || candidates.length === 0) continue;
808
849
  const candidateContent = candidates[0].content;
@@ -838,6 +879,7 @@ function collapseGeminiSSE(rawBody) {
838
879
  arguments: normalizeToolArguments(tc.arguments)
839
880
  }));
840
881
  if (audioB64) return {
882
+ ...usage ? { usage } : {},
841
883
  audioB64,
842
884
  audioMimeType,
843
885
  ...content ? { content } : {},
@@ -850,6 +892,7 @@ function collapseGeminiSSE(rawBody) {
850
892
  if (toolCalls.length > 0) {
851
893
  const blocks = buildOrderedBlocks(orderAtoms);
852
894
  return {
895
+ ...usage ? { usage } : {},
853
896
  ...blocks ? { blocks } : {},
854
897
  ...content ? { content } : {},
855
898
  toolCalls: normalizedToolCalls,
@@ -860,6 +903,7 @@ function collapseGeminiSSE(rawBody) {
860
903
  };
861
904
  }
862
905
  return {
906
+ ...usage ? { usage } : {},
863
907
  content,
864
908
  ...reasoning ? { reasoning } : {},
865
909
  ...droppedChunks > 0 ? { droppedChunks } : {},
@@ -884,6 +928,7 @@ function collapseGeminiSSE(rawBody) {
884
928
  function collapseOllamaNDJSON(rawBody) {
885
929
  const inputTruncated = isCollapseInputTruncated(rawBody);
886
930
  const lines = guardCollapseBody(rawBody).split("\n").filter((l) => l.trim().length > 0);
931
+ let usage;
887
932
  let content = "";
888
933
  let reasoning = "";
889
934
  let droppedChunks = 0;
@@ -901,6 +946,15 @@ function collapseOllamaNDJSON(rawBody) {
901
946
  if (droppedChunks === 1) firstDroppedSample = `parse failed (${err instanceof Error ? err.message : "unknown"}): ${surrogateSafeSlice(line.trim(), 200)}`;
902
947
  continue;
903
948
  }
949
+ usage = captureUsage({
950
+ provider: "ollama",
951
+ contentType: "application/x-ndjson",
952
+ operation: "chat",
953
+ family: "ollama",
954
+ stage: "stream",
955
+ previous: usage,
956
+ observation: parsed
957
+ });
904
958
  const message = parsed.message;
905
959
  if (message) {
906
960
  if (typeof message.content === "string") {
@@ -950,6 +1004,7 @@ function collapseOllamaNDJSON(rawBody) {
950
1004
  arguments: normalizeToolArguments(tc.arguments)
951
1005
  }));
952
1006
  return {
1007
+ ...usage ? { usage } : {},
953
1008
  ...blocks ? { blocks } : {},
954
1009
  ...content ? { content } : {},
955
1010
  toolCalls: normalizedToolCalls,
@@ -962,6 +1017,7 @@ function collapseOllamaNDJSON(rawBody) {
962
1017
  };
963
1018
  }
964
1019
  return {
1020
+ ...usage ? { usage } : {},
965
1021
  content,
966
1022
  ...reasoning ? { reasoning } : {},
967
1023
  ...droppedChunks > 0 ? { droppedChunks } : {},
@@ -980,6 +1036,7 @@ function collapseOllamaNDJSON(rawBody) {
980
1036
  function collapseCohereSSE(rawBody) {
981
1037
  const inputTruncated = isCollapseInputTruncated(rawBody);
982
1038
  const blocks = splitSSEEvents(guardCollapseBody(rawBody));
1039
+ let usage;
983
1040
  let content = "";
984
1041
  let reasoning = "";
985
1042
  let droppedChunks = 0;
@@ -1003,6 +1060,15 @@ function collapseCohereSSE(rawBody) {
1003
1060
  if (droppedChunks === 1) firstDroppedSample = `parse failed (${err instanceof Error ? err.message : "unknown"}): ${surrogateSafeSlice(payload, 200)}`;
1004
1061
  continue;
1005
1062
  }
1063
+ usage = captureUsage({
1064
+ provider: "cohere",
1065
+ contentType: "text/event-stream",
1066
+ operation: "chat",
1067
+ family: "cohere",
1068
+ stage: "stream",
1069
+ previous: usage,
1070
+ observation: parsed
1071
+ });
1006
1072
  if (eventType === "content-delta") {
1007
1073
  const contentObj = (parsed.delta?.message)?.content;
1008
1074
  if (contentObj && contentObj.type === "thinking" && typeof contentObj.thinking === "string") reasoning += contentObj.thinking;
@@ -1063,6 +1129,7 @@ function collapseCohereSSE(rawBody) {
1063
1129
  ...tc.id ? { id: tc.id } : {}
1064
1130
  }));
1065
1131
  return {
1132
+ ...usage ? { usage } : {},
1066
1133
  ...orderedBlocks ? { blocks: orderedBlocks } : {},
1067
1134
  ...content ? { content } : {},
1068
1135
  toolCalls: orderedBlocks ? orderedToolCalls : indexSortedToolCalls,
@@ -1073,6 +1140,7 @@ function collapseCohereSSE(rawBody) {
1073
1140
  };
1074
1141
  }
1075
1142
  return {
1143
+ ...usage ? { usage } : {},
1076
1144
  content,
1077
1145
  ...reasoning ? { reasoning } : {},
1078
1146
  ...droppedChunks > 0 ? { droppedChunks } : {},
@@ -1167,6 +1235,8 @@ function decodeEventStreamFrames(buf) {
1167
1235
  }
1168
1236
  /**
1169
1237
  * Collapse Bedrock binary Event Stream into a single response.
1238
+ * Claude invoke events preserve usage with the Anthropic start/delta rules;
1239
+ * Converse usage remains omitted.
1170
1240
  *
1171
1241
  * Each frame contains a JSON payload with event types like:
1172
1242
  * contentBlockDelta, contentBlockStart, etc.
@@ -1176,6 +1246,7 @@ function collapseBedrockEventStream(rawBody) {
1176
1246
  const inputTruncated = rawBody.byteLength > limit;
1177
1247
  const { frames, truncated: frameTruncated } = decodeEventStreamFrames(inputTruncated ? rawBody.subarray(0, limit) : rawBody);
1178
1248
  const truncated = frameTruncated || inputTruncated;
1249
+ let usage;
1179
1250
  let content = "";
1180
1251
  let reasoning = "";
1181
1252
  let reasoningSignature;
@@ -1204,6 +1275,15 @@ function collapseBedrockEventStream(rawBody) {
1204
1275
  if (droppedChunks === 1) firstDroppedSample = `parse failed (${err instanceof Error ? err.message : "unknown"}): ${surrogateSafeSlice(frameStr, 200)}`;
1205
1276
  continue;
1206
1277
  }
1278
+ usage = captureUsage({
1279
+ provider: "bedrock",
1280
+ contentType: "application/vnd.amazon.eventstream",
1281
+ operation: "chat",
1282
+ family: typeof parsed.type === "string" ? "bedrock-invoke" : "bedrock-converse",
1283
+ stage: "stream",
1284
+ previous: usage,
1285
+ observation: parsed
1286
+ });
1207
1287
  if (parsed.type === "content_block_delta") {
1208
1288
  const delta = parsed.delta;
1209
1289
  if (delta?.type === "text_delta" && typeof delta.text === "string") {
@@ -1311,6 +1391,7 @@ function collapseBedrockEventStream(rawBody) {
1311
1391
  ...tc.id ? { id: tc.id } : {}
1312
1392
  }));
1313
1393
  return {
1394
+ ...usage ? { usage } : {},
1314
1395
  ...orderedBlocks ? { blocks: orderedBlocks } : {},
1315
1396
  ...content ? { content } : {},
1316
1397
  toolCalls: orderedBlocks ? orderedToolCalls : indexSortedToolCalls,
@@ -1323,6 +1404,7 @@ function collapseBedrockEventStream(rawBody) {
1323
1404
  };
1324
1405
  }
1325
1406
  return {
1407
+ ...usage ? { usage } : {},
1326
1408
  content,
1327
1409
  ...reasoning ? { reasoning } : {},
1328
1410
  ...reasoningSignature ? { reasoningSignature } : {},
@@ -1349,6 +1431,7 @@ function collapseBedrockEventStream(rawBody) {
1349
1431
  function collapseGeminiInteractionsSSE(rawBody) {
1350
1432
  const inputTruncated = isCollapseInputTruncated(rawBody);
1351
1433
  const lines = splitSSEEvents(guardCollapseBody(rawBody));
1434
+ let usage;
1352
1435
  let content = "";
1353
1436
  let reasoning = "";
1354
1437
  let droppedChunks = 0;
@@ -1368,6 +1451,15 @@ function collapseGeminiInteractionsSSE(rawBody) {
1368
1451
  if (droppedChunks === 1) firstDroppedSample = `parse failed (${err instanceof Error ? err.message : "unknown"}): ${surrogateSafeSlice(payload, 200)}`;
1369
1452
  continue;
1370
1453
  }
1454
+ usage = captureUsage({
1455
+ provider: "gemini-interactions",
1456
+ contentType: "text/event-stream",
1457
+ operation: "chat",
1458
+ family: "interactions",
1459
+ stage: "stream",
1460
+ previous: usage,
1461
+ observation: parsed
1462
+ });
1371
1463
  const eventType = parsed.event_type;
1372
1464
  if (!eventType) continue;
1373
1465
  const index = typeof parsed.index === "number" ? parsed.index : void 0;
@@ -1425,6 +1517,7 @@ function collapseGeminiInteractionsSSE(rawBody) {
1425
1517
  });
1426
1518
  }
1427
1519
  if (toolCalls.length > 0) return {
1520
+ ...usage ? { usage } : {},
1428
1521
  ...content ? { content } : {},
1429
1522
  toolCalls,
1430
1523
  ...reasoning ? { reasoning } : {},
@@ -1433,6 +1526,7 @@ function collapseGeminiInteractionsSSE(rawBody) {
1433
1526
  ...inputTruncated ? { truncated: true } : {}
1434
1527
  };
1435
1528
  return {
1529
+ ...usage ? { usage } : {},
1436
1530
  content,
1437
1531
  ...reasoning ? { reasoning } : {},
1438
1532
  ...droppedChunks > 0 ? { droppedChunks } : {},
@@ -1458,24 +1552,37 @@ function collapseStreamingResponse(contentType, providerKey, body, logger) {
1458
1552
  */
1459
1553
  function collapseStreamingResponseWithResponsesTools(contentType, providerKey, body, logger) {
1460
1554
  const ct = contentType.toLowerCase();
1461
- if (ct.includes("application/vnd.amazon.eventstream")) return collapseBedrockEventStream(typeof body === "string" ? Buffer.from(body, "binary") : body);
1462
- if (ct.includes("application/x-ndjson")) return collapseOllamaNDJSON(typeof body === "string" ? body : body.toString("utf8"));
1555
+ const complete = (result) => {
1556
+ const usage = captureUsage({
1557
+ provider: providerKey,
1558
+ contentType,
1559
+ family: "stream-dispatch",
1560
+ stage: "collapsed",
1561
+ observation: result
1562
+ });
1563
+ return usage ? {
1564
+ ...result,
1565
+ usage
1566
+ } : result;
1567
+ };
1568
+ if (ct.includes("application/vnd.amazon.eventstream")) return complete(collapseBedrockEventStream(typeof body === "string" ? Buffer.from(body, "binary") : body));
1569
+ if (ct.includes("application/x-ndjson")) return complete(collapseOllamaNDJSON(typeof body === "string" ? body : body.toString("utf8")));
1463
1570
  if (ct.includes("text/event-stream")) {
1464
1571
  const str = typeof body === "string" ? body : body.toString("utf8");
1465
1572
  switch (providerKey) {
1466
1573
  case "openai":
1467
1574
  case "azure":
1468
1575
  case "openrouter":
1469
- case "byteplus": return collapseOpenAISSEWithResponsesTools(str);
1470
- case "anthropic": return collapseAnthropicSSE(str);
1576
+ case "byteplus": return complete(collapseOpenAISSEWithResponsesTools(str));
1577
+ case "anthropic": return complete(collapseAnthropicSSE(str));
1471
1578
  case "gemini":
1472
- case "vertexai": return collapseGeminiSSE(str);
1473
- case "gemini-interactions": return collapseGeminiInteractionsSSE(str);
1474
- case "cohere": return collapseCohereSSE(str);
1475
- case "bedrock": return collapseAnthropicSSE(str);
1579
+ case "vertexai": return complete(collapseGeminiSSE(str));
1580
+ case "gemini-interactions": return complete(collapseGeminiInteractionsSSE(str));
1581
+ case "cohere": return complete(collapseCohereSSE(str));
1582
+ case "bedrock": return complete(collapseAnthropicSSE(str));
1476
1583
  default:
1477
1584
  logger?.warn(`[stream-collapse] unknown SSE provider "${providerKey}", falling back to OpenAI SSE format`);
1478
- return collapseOpenAISSEWithResponsesTools(str);
1585
+ return complete(collapseOpenAISSEWithResponsesTools(str));
1479
1586
  }
1480
1587
  }
1481
1588
  return null;