@copilotkit/aimock 1.43.0 → 1.45.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 (396) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +46 -0
  4. package/README.md +14 -2
  5. package/dist/agui-handler.d.ts.map +1 -1
  6. package/dist/aimock-cli.cjs +31 -5
  7. package/dist/aimock-cli.cjs.map +1 -1
  8. package/dist/aimock-cli.d.cts.map +1 -1
  9. package/dist/aimock-cli.d.ts.map +1 -1
  10. package/dist/aimock-cli.js +31 -5
  11. package/dist/aimock-cli.js.map +1 -1
  12. package/dist/bedrock-converse.cjs +344 -43
  13. package/dist/bedrock-converse.cjs.map +1 -1
  14. package/dist/bedrock-converse.d.cts.map +1 -1
  15. package/dist/bedrock-converse.d.ts.map +1 -1
  16. package/dist/bedrock-converse.js +345 -44
  17. package/dist/bedrock-converse.js.map +1 -1
  18. package/dist/bedrock.cjs +195 -42
  19. package/dist/bedrock.cjs.map +1 -1
  20. package/dist/bedrock.d.cts.map +1 -1
  21. package/dist/bedrock.d.ts.map +1 -1
  22. package/dist/bedrock.js +196 -43
  23. package/dist/bedrock.js.map +1 -1
  24. package/dist/chaos.cjs +9 -5
  25. package/dist/chaos.cjs.map +1 -1
  26. package/dist/chaos.d.cts.map +1 -1
  27. package/dist/chaos.d.ts.map +1 -1
  28. package/dist/chaos.js +10 -7
  29. package/dist/chaos.js.map +1 -1
  30. package/dist/cli.cjs +238 -9
  31. package/dist/cli.cjs.map +1 -1
  32. package/dist/cli.js +242 -13
  33. package/dist/cli.js.map +1 -1
  34. package/dist/cohere.cjs +159 -72
  35. package/dist/cohere.cjs.map +1 -1
  36. package/dist/cohere.d.cts.map +1 -1
  37. package/dist/cohere.d.ts.map +1 -1
  38. package/dist/cohere.js +160 -73
  39. package/dist/cohere.js.map +1 -1
  40. package/dist/config-loader.cjs +63 -5
  41. package/dist/config-loader.cjs.map +1 -1
  42. package/dist/config-loader.d.cts +37 -4
  43. package/dist/config-loader.d.cts.map +1 -1
  44. package/dist/config-loader.d.ts +37 -4
  45. package/dist/config-loader.d.ts.map +1 -1
  46. package/dist/config-loader.js +63 -5
  47. package/dist/config-loader.js.map +1 -1
  48. package/dist/constants.cjs +8 -0
  49. package/dist/constants.cjs.map +1 -1
  50. package/dist/constants.d.cts +6 -2
  51. package/dist/constants.d.ts +6 -2
  52. package/dist/constants.js +8 -1
  53. package/dist/constants.js.map +1 -1
  54. package/dist/echo-text.cjs +65 -0
  55. package/dist/echo-text.cjs.map +1 -0
  56. package/dist/echo-text.d.cts +22 -0
  57. package/dist/echo-text.d.cts.map +1 -0
  58. package/dist/echo-text.d.ts +22 -0
  59. package/dist/echo-text.d.ts.map +1 -0
  60. package/dist/echo-text.js +65 -0
  61. package/dist/echo-text.js.map +1 -0
  62. package/dist/embeddings.cjs +18 -1
  63. package/dist/embeddings.cjs.map +1 -1
  64. package/dist/embeddings.d.cts +1 -1
  65. package/dist/embeddings.d.cts.map +1 -1
  66. package/dist/embeddings.d.ts +1 -1
  67. package/dist/embeddings.d.ts.map +1 -1
  68. package/dist/embeddings.js +18 -1
  69. package/dist/embeddings.js.map +1 -1
  70. package/dist/fakes-plugin.cjs +131 -0
  71. package/dist/fakes-plugin.cjs.map +1 -0
  72. package/dist/fakes-plugin.d.cts +23 -0
  73. package/dist/fakes-plugin.d.cts.map +1 -0
  74. package/dist/fakes-plugin.d.ts +23 -0
  75. package/dist/fakes-plugin.d.ts.map +1 -0
  76. package/dist/fakes-plugin.js +127 -0
  77. package/dist/fakes-plugin.js.map +1 -0
  78. package/dist/files.cjs +9 -11
  79. package/dist/files.cjs.map +1 -1
  80. package/dist/files.d.cts.map +1 -1
  81. package/dist/files.d.ts.map +1 -1
  82. package/dist/files.js +10 -13
  83. package/dist/files.js.map +1 -1
  84. package/dist/fine-tuning.cjs +1 -19
  85. package/dist/fine-tuning.cjs.map +1 -1
  86. package/dist/fine-tuning.d.cts.map +1 -1
  87. package/dist/fine-tuning.d.ts.map +1 -1
  88. package/dist/fine-tuning.js +2 -20
  89. package/dist/fine-tuning.js.map +1 -1
  90. package/dist/fixture-loader-services.cjs +116 -0
  91. package/dist/fixture-loader-services.cjs.map +1 -0
  92. package/dist/fixture-loader-services.d.cts +48 -0
  93. package/dist/fixture-loader-services.d.cts.map +1 -0
  94. package/dist/fixture-loader-services.d.ts +48 -0
  95. package/dist/fixture-loader-services.d.ts.map +1 -0
  96. package/dist/fixture-loader-services.js +114 -0
  97. package/dist/fixture-loader-services.js.map +1 -0
  98. package/dist/fixture-loader.cjs +552 -29
  99. package/dist/fixture-loader.cjs.map +1 -1
  100. package/dist/fixture-loader.d.cts +140 -2
  101. package/dist/fixture-loader.d.cts.map +1 -1
  102. package/dist/fixture-loader.d.ts +140 -2
  103. package/dist/fixture-loader.d.ts.map +1 -1
  104. package/dist/fixture-loader.js +542 -31
  105. package/dist/fixture-loader.js.map +1 -1
  106. package/dist/gemini-embeddings.cjs +42 -2
  107. package/dist/gemini-embeddings.cjs.map +1 -1
  108. package/dist/gemini-embeddings.js +43 -3
  109. package/dist/gemini-embeddings.js.map +1 -1
  110. package/dist/gemini-interactions.cjs +288 -52
  111. package/dist/gemini-interactions.cjs.map +1 -1
  112. package/dist/gemini-interactions.d.cts.map +1 -1
  113. package/dist/gemini-interactions.d.ts.map +1 -1
  114. package/dist/gemini-interactions.js +289 -53
  115. package/dist/gemini-interactions.js.map +1 -1
  116. package/dist/gemini.cjs +234 -38
  117. package/dist/gemini.cjs.map +1 -1
  118. package/dist/gemini.d.cts.map +1 -1
  119. package/dist/gemini.d.ts.map +1 -1
  120. package/dist/gemini.js +235 -39
  121. package/dist/gemini.js.map +1 -1
  122. package/dist/helpers.cjs +1157 -12
  123. package/dist/helpers.cjs.map +1 -1
  124. package/dist/helpers.d.cts +85 -4
  125. package/dist/helpers.d.cts.map +1 -1
  126. package/dist/helpers.d.ts +85 -4
  127. package/dist/helpers.d.ts.map +1 -1
  128. package/dist/helpers.js +1113 -14
  129. package/dist/helpers.js.map +1 -1
  130. package/dist/images.cjs +3 -2
  131. package/dist/images.cjs.map +1 -1
  132. package/dist/images.js +3 -2
  133. package/dist/images.js.map +1 -1
  134. package/dist/index.cjs +39 -1
  135. package/dist/index.d.cts +11 -4
  136. package/dist/index.d.ts +11 -4
  137. package/dist/index.js +11 -4
  138. package/dist/jest.cjs +43 -14
  139. package/dist/jest.cjs.map +1 -1
  140. package/dist/jest.d.cts +47 -5
  141. package/dist/jest.d.cts.map +1 -1
  142. package/dist/jest.d.ts +47 -5
  143. package/dist/jest.d.ts.map +1 -1
  144. package/dist/jest.js +45 -16
  145. package/dist/jest.js.map +1 -1
  146. package/dist/journal.cjs +155 -13
  147. package/dist/journal.cjs.map +1 -1
  148. package/dist/journal.d.cts +54 -4
  149. package/dist/journal.d.cts.map +1 -1
  150. package/dist/journal.d.ts +54 -4
  151. package/dist/journal.d.ts.map +1 -1
  152. package/dist/journal.js +155 -13
  153. package/dist/journal.js.map +1 -1
  154. package/dist/live-sanitize.cjs +4 -32
  155. package/dist/live-sanitize.cjs.map +1 -1
  156. package/dist/live-sanitize.js +4 -32
  157. package/dist/live-sanitize.js.map +1 -1
  158. package/dist/llmock.cjs +204 -39
  159. package/dist/llmock.cjs.map +1 -1
  160. package/dist/llmock.d.cts +51 -1
  161. package/dist/llmock.d.cts.map +1 -1
  162. package/dist/llmock.d.ts +51 -1
  163. package/dist/llmock.d.ts.map +1 -1
  164. package/dist/llmock.js +206 -41
  165. package/dist/llmock.js.map +1 -1
  166. package/dist/mcp-fakes-mount.cjs +217 -0
  167. package/dist/mcp-fakes-mount.cjs.map +1 -0
  168. package/dist/mcp-fakes-mount.js +211 -0
  169. package/dist/mcp-fakes-mount.js.map +1 -0
  170. package/dist/mcp-fakes-report.cjs +111 -0
  171. package/dist/mcp-fakes-report.cjs.map +1 -0
  172. package/dist/mcp-fakes-report.d.cts +40 -0
  173. package/dist/mcp-fakes-report.d.cts.map +1 -0
  174. package/dist/mcp-fakes-report.d.ts +40 -0
  175. package/dist/mcp-fakes-report.d.ts.map +1 -0
  176. package/dist/mcp-fakes-report.js +107 -0
  177. package/dist/mcp-fakes-report.js.map +1 -0
  178. package/dist/mcp-fakes.cjs +1942 -0
  179. package/dist/mcp-fakes.cjs.map +1 -0
  180. package/dist/mcp-fakes.d.cts +504 -0
  181. package/dist/mcp-fakes.d.cts.map +1 -0
  182. package/dist/mcp-fakes.d.ts +504 -0
  183. package/dist/mcp-fakes.d.ts.map +1 -0
  184. package/dist/mcp-fakes.js +1937 -0
  185. package/dist/mcp-fakes.js.map +1 -0
  186. package/dist/mcp-handler.cjs +534 -27
  187. package/dist/mcp-handler.cjs.map +1 -1
  188. package/dist/mcp-handler.d.cts +49 -0
  189. package/dist/mcp-handler.d.cts.map +1 -0
  190. package/dist/mcp-handler.d.ts +49 -0
  191. package/dist/mcp-handler.d.ts.map +1 -0
  192. package/dist/mcp-handler.js +530 -28
  193. package/dist/mcp-handler.js.map +1 -1
  194. package/dist/mcp-mock.cjs +326 -47
  195. package/dist/mcp-mock.cjs.map +1 -1
  196. package/dist/mcp-mock.d.cts +97 -1
  197. package/dist/mcp-mock.d.cts.map +1 -1
  198. package/dist/mcp-mock.d.ts +97 -1
  199. package/dist/mcp-mock.d.ts.map +1 -1
  200. package/dist/mcp-mock.js +327 -48
  201. package/dist/mcp-mock.js.map +1 -1
  202. package/dist/mcp-recorder.cjs +1224 -0
  203. package/dist/mcp-recorder.cjs.map +1 -0
  204. package/dist/mcp-recorder.d.cts +108 -0
  205. package/dist/mcp-recorder.d.cts.map +1 -0
  206. package/dist/mcp-recorder.d.ts +108 -0
  207. package/dist/mcp-recorder.d.ts.map +1 -0
  208. package/dist/mcp-recorder.js +1215 -0
  209. package/dist/mcp-recorder.js.map +1 -0
  210. package/dist/mcp-stub.cjs +5 -1
  211. package/dist/mcp-stub.d.cts +3 -1
  212. package/dist/mcp-stub.d.ts +3 -1
  213. package/dist/mcp-stub.js +3 -1
  214. package/dist/mcp-types.d.cts +6 -0
  215. package/dist/mcp-types.d.ts +6 -0
  216. package/dist/message-text.cjs +192 -0
  217. package/dist/message-text.cjs.map +1 -0
  218. package/dist/message-text.d.cts +31 -0
  219. package/dist/message-text.d.cts.map +1 -0
  220. package/dist/message-text.d.ts +31 -0
  221. package/dist/message-text.d.ts.map +1 -0
  222. package/dist/message-text.js +184 -0
  223. package/dist/message-text.js.map +1 -0
  224. package/dist/messages.cjs +400 -56
  225. package/dist/messages.cjs.map +1 -1
  226. package/dist/messages.d.cts.map +1 -1
  227. package/dist/messages.d.ts.map +1 -1
  228. package/dist/messages.js +401 -58
  229. package/dist/messages.js.map +1 -1
  230. package/dist/metrics.cjs +46 -66
  231. package/dist/metrics.cjs.map +1 -1
  232. package/dist/metrics.d.cts +14 -6
  233. package/dist/metrics.d.cts.map +1 -1
  234. package/dist/metrics.d.ts +14 -6
  235. package/dist/metrics.d.ts.map +1 -1
  236. package/dist/metrics.js +32 -40
  237. package/dist/metrics.js.map +1 -1
  238. package/dist/misbehavior.cjs +1523 -0
  239. package/dist/misbehavior.cjs.map +1 -0
  240. package/dist/misbehavior.d.cts +43 -0
  241. package/dist/misbehavior.d.cts.map +1 -0
  242. package/dist/misbehavior.d.ts +43 -0
  243. package/dist/misbehavior.d.ts.map +1 -0
  244. package/dist/misbehavior.js +1511 -0
  245. package/dist/misbehavior.js.map +1 -0
  246. package/dist/ollama.cjs +315 -113
  247. package/dist/ollama.cjs.map +1 -1
  248. package/dist/ollama.d.cts.map +1 -1
  249. package/dist/ollama.d.ts.map +1 -1
  250. package/dist/ollama.js +316 -114
  251. package/dist/ollama.js.map +1 -1
  252. package/dist/openapi.cjs +3405 -0
  253. package/dist/openapi.cjs.map +1 -0
  254. package/dist/openapi.d.cts +30 -0
  255. package/dist/openapi.d.cts.map +1 -0
  256. package/dist/openapi.d.ts +30 -0
  257. package/dist/openapi.d.ts.map +1 -0
  258. package/dist/openapi.js +3404 -0
  259. package/dist/openapi.js.map +1 -0
  260. package/dist/openrouter-video.cjs +4 -4
  261. package/dist/openrouter-video.cjs.map +1 -1
  262. package/dist/openrouter-video.d.cts.map +1 -1
  263. package/dist/openrouter-video.d.ts.map +1 -1
  264. package/dist/openrouter-video.js +4 -4
  265. package/dist/openrouter-video.js.map +1 -1
  266. package/dist/record-sanitize.cjs +231 -0
  267. package/dist/record-sanitize.cjs.map +1 -0
  268. package/dist/record-sanitize.js +224 -0
  269. package/dist/record-sanitize.js.map +1 -0
  270. package/dist/recorder.cjs +115 -6
  271. package/dist/recorder.cjs.map +1 -1
  272. package/dist/recorder.d.cts +2 -1
  273. package/dist/recorder.d.cts.map +1 -1
  274. package/dist/recorder.d.ts +2 -1
  275. package/dist/recorder.d.ts.map +1 -1
  276. package/dist/recorder.js +116 -8
  277. package/dist/recorder.js.map +1 -1
  278. package/dist/responses.cjs +701 -166
  279. package/dist/responses.cjs.map +1 -1
  280. package/dist/responses.d.cts +5 -13
  281. package/dist/responses.d.cts.map +1 -1
  282. package/dist/responses.d.ts +5 -13
  283. package/dist/responses.d.ts.map +1 -1
  284. package/dist/responses.js +699 -169
  285. package/dist/responses.js.map +1 -1
  286. package/dist/route-registry.cjs +951 -0
  287. package/dist/route-registry.cjs.map +1 -0
  288. package/dist/route-registry.d.cts +33 -0
  289. package/dist/route-registry.d.cts.map +1 -0
  290. package/dist/route-registry.d.ts +33 -0
  291. package/dist/route-registry.d.ts.map +1 -0
  292. package/dist/route-registry.js +866 -0
  293. package/dist/route-registry.js.map +1 -0
  294. package/dist/router.cjs +24 -2
  295. package/dist/router.cjs.map +1 -1
  296. package/dist/router.d.cts.map +1 -1
  297. package/dist/router.d.ts.map +1 -1
  298. package/dist/router.js +25 -4
  299. package/dist/router.js.map +1 -1
  300. package/dist/server.cjs +1159 -264
  301. package/dist/server.cjs.map +1 -1
  302. package/dist/server.d.cts +4 -1
  303. package/dist/server.d.cts.map +1 -1
  304. package/dist/server.d.ts +4 -1
  305. package/dist/server.d.ts.map +1 -1
  306. package/dist/server.js +1067 -172
  307. package/dist/server.js.map +1 -1
  308. package/dist/speech.cjs +4 -2
  309. package/dist/speech.cjs.map +1 -1
  310. package/dist/speech.js +4 -2
  311. package/dist/speech.js.map +1 -1
  312. package/dist/stream-collapse.cjs +236 -34
  313. package/dist/stream-collapse.cjs.map +1 -1
  314. package/dist/stream-collapse.d.cts +39 -4
  315. package/dist/stream-collapse.d.cts.map +1 -1
  316. package/dist/stream-collapse.d.ts +39 -4
  317. package/dist/stream-collapse.d.ts.map +1 -1
  318. package/dist/stream-collapse.js +235 -35
  319. package/dist/stream-collapse.js.map +1 -1
  320. package/dist/suite.cjs +1 -1
  321. package/dist/suite.js +1 -1
  322. package/dist/transcription.cjs +2 -2
  323. package/dist/transcription.cjs.map +1 -1
  324. package/dist/transcription.d.cts.map +1 -1
  325. package/dist/transcription.d.ts.map +1 -1
  326. package/dist/transcription.js +2 -2
  327. package/dist/transcription.js.map +1 -1
  328. package/dist/types.cjs +18 -0
  329. package/dist/types.cjs.map +1 -0
  330. package/dist/types.d.cts +516 -5
  331. package/dist/types.d.cts.map +1 -1
  332. package/dist/types.d.ts +516 -5
  333. package/dist/types.d.ts.map +1 -1
  334. package/dist/types.js +17 -0
  335. package/dist/types.js.map +1 -0
  336. package/dist/validate-cli.cjs +123 -33
  337. package/dist/validate-cli.cjs.map +1 -1
  338. package/dist/validate-cli.js +125 -35
  339. package/dist/validate-cli.js.map +1 -1
  340. package/dist/vector-stores.cjs +1180 -0
  341. package/dist/vector-stores.cjs.map +1 -0
  342. package/dist/vector-stores.d.cts +106 -0
  343. package/dist/vector-stores.d.cts.map +1 -0
  344. package/dist/vector-stores.d.ts +106 -0
  345. package/dist/vector-stores.d.ts.map +1 -0
  346. package/dist/vector-stores.js +1164 -0
  347. package/dist/vector-stores.js.map +1 -0
  348. package/dist/vector-types.d.cts.map +1 -1
  349. package/dist/version.cjs +45 -0
  350. package/dist/version.cjs.map +1 -0
  351. package/dist/version.js +44 -0
  352. package/dist/version.js.map +1 -0
  353. package/dist/video.cjs +19 -0
  354. package/dist/video.cjs.map +1 -1
  355. package/dist/video.d.cts.map +1 -1
  356. package/dist/video.d.ts.map +1 -1
  357. package/dist/video.js +19 -0
  358. package/dist/video.js.map +1 -1
  359. package/dist/vitest.cjs +77 -16
  360. package/dist/vitest.cjs.map +1 -1
  361. package/dist/vitest.d.cts +38 -5
  362. package/dist/vitest.d.cts.map +1 -1
  363. package/dist/vitest.d.ts +38 -5
  364. package/dist/vitest.d.ts.map +1 -1
  365. package/dist/vitest.js +78 -17
  366. package/dist/vitest.js.map +1 -1
  367. package/dist/watcher.cjs +6 -2
  368. package/dist/watcher.cjs.map +1 -1
  369. package/dist/watcher.js +6 -2
  370. package/dist/watcher.js.map +1 -1
  371. package/dist/ws-gemini-live.cjs +210 -101
  372. package/dist/ws-gemini-live.cjs.map +1 -1
  373. package/dist/ws-gemini-live.d.cts +9 -3
  374. package/dist/ws-gemini-live.d.cts.map +1 -1
  375. package/dist/ws-gemini-live.d.ts +9 -3
  376. package/dist/ws-gemini-live.d.ts.map +1 -1
  377. package/dist/ws-gemini-live.js +211 -102
  378. package/dist/ws-gemini-live.js.map +1 -1
  379. package/dist/ws-realtime.cjs +175 -62
  380. package/dist/ws-realtime.cjs.map +1 -1
  381. package/dist/ws-realtime.d.cts +8 -3
  382. package/dist/ws-realtime.d.cts.map +1 -1
  383. package/dist/ws-realtime.d.ts +8 -3
  384. package/dist/ws-realtime.d.ts.map +1 -1
  385. package/dist/ws-realtime.js +176 -63
  386. package/dist/ws-realtime.js.map +1 -1
  387. package/dist/ws-responses.cjs +121 -16
  388. package/dist/ws-responses.cjs.map +1 -1
  389. package/dist/ws-responses.d.cts +8 -12
  390. package/dist/ws-responses.d.cts.map +1 -1
  391. package/dist/ws-responses.d.ts +8 -12
  392. package/dist/ws-responses.d.ts.map +1 -1
  393. package/dist/ws-responses.js +123 -18
  394. package/dist/ws-responses.js.map +1 -1
  395. package/package.json +13 -2
  396. package/skills/write-fixtures/SKILL.md +179 -21
package/dist/gemini.cjs CHANGED
@@ -1,6 +1,7 @@
1
1
  const require_helpers = require('./helpers.cjs');
2
2
  const require_sse_writer = require('./sse-writer.cjs');
3
3
  const require_chaos = require('./chaos.cjs');
4
+ const require_misbehavior = require('./misbehavior.cjs');
4
5
  const require_router = require('./router.cjs');
5
6
  const require_recorder = require('./recorder.cjs');
6
7
  const require_interruption = require('./interruption.cjs');
@@ -29,7 +30,14 @@ function validateGeminiBody(req) {
29
30
  const parts = req.systemInstruction.parts;
30
31
  if (parts !== void 0 && parts !== null && !Array.isArray(parts)) return "systemInstruction.parts must be an array";
31
32
  }
32
- return require_helpers.validateToolsField(req.tools);
33
+ const toolsError = require_helpers.validateToolsField(req.tools);
34
+ if (toolsError) return toolsError;
35
+ if (Array.isArray(req.tools)) for (const [toolIndex, tool] of req.tools.entries()) {
36
+ if (!Array.isArray(tool.functionDeclarations)) continue;
37
+ const declarationIndex = tool.functionDeclarations.findIndex((declaration) => declaration === null);
38
+ if (declarationIndex !== -1) return `tools[${toolIndex}].functionDeclarations[${declarationIndex}] must not be null`;
39
+ }
40
+ return null;
33
41
  }
34
42
  function geminiToCompletionRequest(req, model, stream) {
35
43
  const messages = [];
@@ -108,7 +116,7 @@ function geminiToCompletionRequest(req, model, stream) {
108
116
  function: {
109
117
  name: d.name,
110
118
  description: d.description,
111
- parameters: d.parameters
119
+ parameters: d.parameters ?? d.parametersJsonSchema
112
120
  }
113
121
  }));
114
122
  }
@@ -192,16 +200,10 @@ function buildGeminiTextStreamChunks(content, chunkSize, reasoning, overrides) {
192
200
  return chunks;
193
201
  }
194
202
  function parseToolCallPart(tc, logger) {
195
- let argsObj;
196
- try {
197
- argsObj = JSON.parse(tc.arguments || "{}");
198
- } catch {
199
- logger.warn(`Malformed JSON in fixture tool call arguments for "${tc.name}": ${tc.arguments}`);
200
- argsObj = {};
201
- }
203
+ const args = require_helpers.servedToolArgs(tc, "object", logger);
202
204
  const functionCall = {
203
205
  name: tc.name,
204
- args: argsObj
206
+ args: args.value
205
207
  };
206
208
  if (tc.id) functionCall.id = tc.id;
207
209
  return { functionCall };
@@ -418,24 +420,24 @@ function resolveAudioInlineData(audio) {
418
420
  data: audio.audio.b64Json
419
421
  };
420
422
  }
421
- function buildGeminiAudioParts(audio, logger, effReasoning) {
423
+ function buildGeminiAudioParts(audio, toolCalls, logger, effReasoning) {
422
424
  const parts = [{ inlineData: resolveAudioInlineData(audio) }];
423
425
  if (effReasoning) parts.push({
424
426
  text: effReasoning,
425
427
  thought: true
426
428
  });
427
429
  if (audio.content) parts.push({ text: audio.content });
428
- if (audio.toolCalls?.length) parts.push(...audio.toolCalls.map((tc) => parseToolCallPart(tc, logger)));
430
+ if (toolCalls.length) parts.push(...toolCalls.map((tc) => parseToolCallPart(tc, logger)));
429
431
  return parts;
430
432
  }
431
- function buildGeminiAudioResponse(audio, logger, effReasoning) {
433
+ function buildGeminiAudioResponse(audio, toolCalls, logger, effReasoning) {
432
434
  return {
433
435
  candidates: [{
434
436
  content: {
435
437
  role: "model",
436
- parts: buildGeminiAudioParts(audio, logger, effReasoning)
438
+ parts: buildGeminiAudioParts(audio, toolCalls, logger, effReasoning)
437
439
  },
438
- finishReason: audio.toolCalls?.length ? "FUNCTION_CALL" : "STOP",
440
+ finishReason: toolCalls.length ? "FUNCTION_CALL" : "STOP",
439
441
  index: 0
440
442
  }],
441
443
  usageMetadata: {
@@ -445,14 +447,14 @@ function buildGeminiAudioResponse(audio, logger, effReasoning) {
445
447
  }
446
448
  };
447
449
  }
448
- function buildGeminiAudioStreamChunks(audio, logger, effReasoning) {
450
+ function buildGeminiAudioStreamChunks(audio, toolCalls, logger, effReasoning) {
449
451
  return [{
450
452
  candidates: [{
451
453
  content: {
452
454
  role: "model",
453
- parts: buildGeminiAudioParts(audio, logger, effReasoning)
455
+ parts: buildGeminiAudioParts(audio, toolCalls, logger, effReasoning)
454
456
  },
455
- finishReason: audio.toolCalls?.length ? "FUNCTION_CALL" : "STOP",
457
+ finishReason: toolCalls.length ? "FUNCTION_CALL" : "STOP",
456
458
  index: 0
457
459
  }],
458
460
  usageMetadata: {
@@ -487,8 +489,90 @@ async function writeGeminiSSEStream(res, chunks, optionsOrLatency) {
487
489
  if (!res.writableEnded) res.end();
488
490
  return true;
489
491
  }
492
+ /** Prepare native fault output once; the journal describes these exact parts. */
493
+ function prepareGeminiMisbehavior(plan, request, streaming, chunkSize, logger, strict) {
494
+ const response = plan.response;
495
+ const combined = require_helpers.isCombinedFixtureResponse(response);
496
+ if (!(combined || require_helpers.isToolCallResponse(response) || require_helpers.isTextResponse(response))) throw new Error("Applied Gemini misbehavior requires a chat response");
497
+ const outcome = combined && response.blocks?.length ? require_helpers.resolveFixtureBlockOutcome(response.blocks) : void 0;
498
+ const content = outcome?.content ?? ("content" in response ? response.content ?? "" : "");
499
+ const calls = outcome?.toolCalls ?? ("toolCalls" in response ? response.toolCalls ?? [] : []);
500
+ const overrides = require_helpers.extractOverrides(response);
501
+ delete overrides.usage;
502
+ const fault = plan.summary.fault;
503
+ const candidate = {
504
+ content: {
505
+ role: "model",
506
+ parts: []
507
+ },
508
+ index: 0
509
+ };
510
+ let chunks;
511
+ if (fault === "tool-args-invalid-json") {
512
+ const target = calls[plan.target?.index ?? 0];
513
+ if (!target) throw new Error("Gemini malformed-call plan requires its selected tool call");
514
+ chunks = [{ candidates: [{
515
+ index: 0,
516
+ finishReason: "MALFORMED_FUNCTION_CALL",
517
+ finishMessage: `Malformed function call: ${target.name}(${target.arguments})`
518
+ }] }];
519
+ } else if (fault === "tool-unknown-name" && !request.tools?.length) {
520
+ candidate.finishReason = "UNEXPECTED_TOOL_CALL";
521
+ chunks = [{ candidates: [candidate] }];
522
+ } else if (fault === "stop-length-mid-tool") {
523
+ candidate.content.parts = content ? [{ text: content }] : [];
524
+ candidate.finishReason = "MAX_TOKENS";
525
+ chunks = [{ candidates: [candidate] }];
526
+ } else if (fault === "empty-response") {
527
+ candidate.content.parts = [{ text: "" }];
528
+ candidate.finishReason = "STOP";
529
+ chunks = [{ candidates: [candidate] }];
530
+ } else if (fault === "content-filter") {
531
+ candidate.finishReason = "SAFETY";
532
+ candidate.safetyRatings = [{
533
+ category: "HARM_CATEGORY_DANGEROUS_CONTENT",
534
+ probability: "HIGH",
535
+ blocked: true
536
+ }];
537
+ chunks = [{ candidates: [candidate] }];
538
+ } else if (fault === "reasoning-only") {
539
+ candidate.content.parts = [{
540
+ text: plan.reasoning ?? "",
541
+ thought: true
542
+ }];
543
+ candidate.finishReason = "MAX_TOKENS";
544
+ chunks = [{ candidates: [candidate] }];
545
+ } else {
546
+ const reasoning = require_helpers.resolveReasoningForModel(response.reasoning, request.model, strict, logger);
547
+ if (fault === "tool-unknown-name") overrides.finishReason = "stop";
548
+ if (combined) chunks = streaming ? buildGeminiContentWithToolCallsStreamChunks(content, calls, chunkSize, logger, reasoning, overrides, response.blocks) : [buildGeminiContentWithToolCallsResponse(content, calls, logger, reasoning, overrides, response.blocks)];
549
+ else if (require_helpers.isToolCallResponse(response)) chunks = streaming ? buildGeminiToolCallStreamChunks(calls, chunkSize, logger, reasoning, overrides) : [buildGeminiToolCallResponse(calls, logger, reasoning, overrides)];
550
+ else chunks = streaming ? buildGeminiTextStreamChunks(content, chunkSize, reasoning, overrides) : [buildGeminiTextResponse(content, reasoning, overrides)];
551
+ }
552
+ const parts = chunks.flatMap((chunk) => chunk.candidates.flatMap((item) => item.content?.parts ?? []));
553
+ const servedToolCalls = parts.flatMap((part) => part.functionCall ? [{
554
+ name: part.functionCall.name,
555
+ arguments: JSON.stringify(part.functionCall.args),
556
+ ...part.functionCall.id ? { id: part.functionCall.id } : {}
557
+ }] : []);
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(""));
559
+ 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
+ };
565
+ return {
566
+ chunks,
567
+ summary: {
568
+ ...plan.summary,
569
+ servedToolCalls
570
+ }
571
+ };
572
+ }
490
573
  async function handleGemini(req, res, raw, model, streaming, fixtures, journal, defaults, setCorsHeaders, providerKey = "gemini") {
491
574
  const { logger } = defaults;
575
+ const wire = providerKey === "vertexai" ? "Vertex AI" : "Gemini";
492
576
  setCorsHeaders(res);
493
577
  let geminiReq;
494
578
  try {
@@ -623,21 +707,101 @@ async function handleGemini(req, res, raw, model, streaming, fixtures, journal,
623
707
  return;
624
708
  }
625
709
  const response = await require_helpers.resolveResponse(fixture, completionReq);
710
+ const misbehavior = require_misbehavior.planMisbehavior({
711
+ wire: "gemini",
712
+ toolCallIdMode: "authored-nonempty",
713
+ fixture,
714
+ response,
715
+ request: completionReq,
716
+ stream: streaming,
717
+ defaults,
718
+ rawHeaders: req.headers,
719
+ url: req.url
720
+ });
721
+ if (misbehavior.kind === "error") {
722
+ require_misbehavior.recordMisbehaviorOutcome({
723
+ entry: journal.add({
724
+ method: req.method ?? "POST",
725
+ path,
726
+ headers: require_helpers.flattenHeaders(req.headers),
727
+ body: completionReq,
728
+ response: {
729
+ status: misbehavior.status,
730
+ fixture,
731
+ error: misbehavior.message
732
+ }
733
+ }),
734
+ summary: misbehavior.summary,
735
+ defaults,
736
+ testId
737
+ });
738
+ 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,
741
+ message: misbehavior.message,
742
+ status: misbehavior.status === 400 ? "INVALID_ARGUMENT" : "UNIMPLEMENTED"
743
+ } }));
744
+ return;
745
+ }
626
746
  const latency = fixture.latency ?? defaults.latency;
627
747
  const chunkSize = Math.max(1, fixture.chunkSize ?? defaults.chunkSize);
628
748
  const replaySpeed = fixture.replaySpeed ?? defaults.replaySpeed;
629
- if (require_helpers.isErrorResponse(response)) {
630
- const status = response.status ?? 500;
631
- journal.add({
749
+ if (misbehavior.kind === "applied") {
750
+ const prepared = prepareGeminiMisbehavior(misbehavior, completionReq, streaming, chunkSize, logger, require_helpers.resolveStrictMode(defaults.strict, req.headers));
751
+ const entry = journal.add({
632
752
  method: req.method ?? "POST",
633
753
  path,
634
754
  headers: require_helpers.flattenHeaders(req.headers),
635
755
  body: completionReq,
636
756
  response: {
637
- status,
757
+ status: 200,
638
758
  fixture
639
759
  }
640
760
  });
761
+ require_misbehavior.recordMisbehaviorOutcome({
762
+ entry,
763
+ summary: prepared.summary,
764
+ defaults,
765
+ testId
766
+ });
767
+ 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
+ }
786
+ return;
787
+ }
788
+ if (require_helpers.isErrorResponse(response)) {
789
+ const status = response.status ?? 500;
790
+ require_misbehavior.recordMisbehaviorOutcome({
791
+ entry: journal.add({
792
+ method: req.method ?? "POST",
793
+ path,
794
+ headers: require_helpers.flattenHeaders(req.headers),
795
+ body: completionReq,
796
+ response: {
797
+ status,
798
+ fixture
799
+ }
800
+ }),
801
+ summary: misbehavior.summary,
802
+ defaults,
803
+ testId
804
+ });
641
805
  const geminiError = { error: {
642
806
  code: status,
643
807
  message: response.error.message,
@@ -659,12 +823,19 @@ async function handleGemini(req, res, raw, model, streaming, fixtures, journal,
659
823
  fixture
660
824
  }
661
825
  });
826
+ require_misbehavior.recordMisbehaviorOutcome({
827
+ entry: journalEntry,
828
+ summary: misbehavior.summary,
829
+ defaults,
830
+ testId
831
+ });
832
+ const audioToolCalls = Array.isArray(response.toolCalls) ? require_helpers.requireServedFunctionToolCalls(response, wire) : [];
662
833
  if (!streaming) {
663
- const body = buildGeminiAudioResponse(response, logger, effReasoning);
834
+ const body = buildGeminiAudioResponse(response, audioToolCalls, logger, effReasoning);
664
835
  res.writeHead(200, { "Content-Type": "application/json" });
665
836
  res.end(JSON.stringify(body));
666
837
  } else {
667
- const chunks = buildGeminiAudioStreamChunks(response, logger, effReasoning);
838
+ const chunks = buildGeminiAudioStreamChunks(response, audioToolCalls, logger, effReasoning);
668
839
  const interruption = require_interruption.createInterruptionSignal(fixture);
669
840
  if (!await writeGeminiSSEStream(res, chunks, {
670
841
  latency,
@@ -682,7 +853,7 @@ async function handleGemini(req, res, raw, model, streaming, fixtures, journal,
682
853
  }
683
854
  return;
684
855
  }
685
- if (require_helpers.isContentWithToolCallsResponse(response)) {
856
+ if (require_helpers.isCombinedFixtureResponse(response)) {
686
857
  if (response.webSearches?.length) logger.warn("webSearches in fixture response are not supported for Gemini API — ignoring");
687
858
  const overrides = require_helpers.extractOverrides(response);
688
859
  const effectiveStrict = require_helpers.resolveStrictMode(defaults.strict, req.headers);
@@ -697,12 +868,19 @@ async function handleGemini(req, res, raw, model, streaming, fixtures, journal,
697
868
  fixture
698
869
  }
699
870
  });
871
+ require_misbehavior.recordMisbehaviorOutcome({
872
+ entry: journalEntry,
873
+ summary: misbehavior.summary,
874
+ defaults,
875
+ testId
876
+ });
877
+ const functionToolCalls = require_helpers.requireEmittedFunctionToolCalls(response, wire);
700
878
  if (!streaming) {
701
- const body = buildGeminiContentWithToolCallsResponse(response.content ?? "", response.toolCalls ?? [], logger, effReasoning, overrides, response.blocks);
879
+ const body = buildGeminiContentWithToolCallsResponse(response.content ?? "", functionToolCalls, logger, effReasoning, overrides, response.blocks);
702
880
  res.writeHead(200, { "Content-Type": "application/json" });
703
881
  res.end(JSON.stringify(body));
704
882
  } else {
705
- const chunks = buildGeminiContentWithToolCallsStreamChunks(response.content ?? "", response.toolCalls ?? [], chunkSize, logger, effReasoning, overrides, response.blocks);
883
+ const chunks = buildGeminiContentWithToolCallsStreamChunks(response.content ?? "", functionToolCalls, chunkSize, logger, effReasoning, overrides, response.blocks);
706
884
  const interruption = require_interruption.createInterruptionSignal(fixture);
707
885
  if (!await writeGeminiSSEStream(res, chunks, {
708
886
  latency,
@@ -735,6 +913,12 @@ async function handleGemini(req, res, raw, model, streaming, fixtures, journal,
735
913
  fixture
736
914
  }
737
915
  });
916
+ require_misbehavior.recordMisbehaviorOutcome({
917
+ entry: journalEntry,
918
+ summary: misbehavior.summary,
919
+ defaults,
920
+ testId
921
+ });
738
922
  if (!streaming) {
739
923
  const body = buildGeminiTextResponse(response.content, effReasoning, overrides);
740
924
  res.writeHead(200, { "Content-Type": "application/json" });
@@ -773,12 +957,19 @@ async function handleGemini(req, res, raw, model, streaming, fixtures, journal,
773
957
  fixture
774
958
  }
775
959
  });
960
+ require_misbehavior.recordMisbehaviorOutcome({
961
+ entry: journalEntry,
962
+ summary: misbehavior.summary,
963
+ defaults,
964
+ testId
965
+ });
966
+ const functionToolCalls = require_helpers.requireEmittedFunctionToolCalls(response, wire);
776
967
  if (!streaming) {
777
- const body = buildGeminiToolCallResponse(response.toolCalls, logger, effReasoning, overrides);
968
+ const body = buildGeminiToolCallResponse(functionToolCalls, logger, effReasoning, overrides);
778
969
  res.writeHead(200, { "Content-Type": "application/json" });
779
970
  res.end(JSON.stringify(body));
780
971
  } else {
781
- const chunks = buildGeminiToolCallStreamChunks(response.toolCalls, chunkSize, logger, effReasoning, overrides);
972
+ const chunks = buildGeminiToolCallStreamChunks(functionToolCalls, chunkSize, logger, effReasoning, overrides);
782
973
  const interruption = require_interruption.createInterruptionSignal(fixture);
783
974
  if (!await writeGeminiSSEStream(res, chunks, {
784
975
  latency,
@@ -796,15 +987,20 @@ async function handleGemini(req, res, raw, model, streaming, fixtures, journal,
796
987
  }
797
988
  return;
798
989
  }
799
- journal.add({
800
- method: req.method ?? "POST",
801
- path,
802
- headers: require_helpers.flattenHeaders(req.headers),
803
- body: completionReq,
804
- response: {
805
- status: 500,
806
- fixture
807
- }
990
+ require_misbehavior.recordMisbehaviorOutcome({
991
+ entry: journal.add({
992
+ method: req.method ?? "POST",
993
+ path,
994
+ headers: require_helpers.flattenHeaders(req.headers),
995
+ body: completionReq,
996
+ response: {
997
+ status: 500,
998
+ fixture
999
+ }
1000
+ }),
1001
+ summary: misbehavior.summary,
1002
+ defaults,
1003
+ testId
808
1004
  });
809
1005
  require_sse_writer.writeErrorResponse(res, 500, JSON.stringify({ error: {
810
1006
  message: "Fixture response did not match any known type",