@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/ollama.js CHANGED
@@ -1,6 +1,7 @@
1
- import { flattenHeaders, generateDeterministicEmbedding, getContext, getTestId, isContentWithToolCallsResponse, isEmbeddingResponse, isErrorResponse, isJsonObject, isTextResponse, isToolCallResponse, normalizeEmbeddingInput, resolveFixtureBlocks, resolveReasoningForModel, resolveResponse, resolveStrictMode, serializeErrorResponse, strictNoMatchLogLine, strictNoMatchMessage, strictOverrideField, validateChatMessages, validateToolsField } from "./helpers.js";
1
+ import { InvalidToolArgumentsError, estimatePromptTokens, estimateTokens, flattenHeaders, generateDeterministicEmbedding, getContext, getTestId, isCombinedFixtureResponse, isEmbeddingResponse, isErrorResponse, isJsonObject, isTextResponse, isToolCallResponse, normalizeEmbeddingInput, requireEmittedFunctionToolCalls, resolveFixtureBlockOutcome, resolveFixtureBlocks, resolveReasoningForModel, resolveResponse, resolveStrictMode, serializeErrorResponse, servedToolArgs, strictNoMatchLogLine, strictNoMatchMessage, strictOverrideField, toolArgsForWire, validateChatMessages, validateToolsField } from "./helpers.js";
2
2
  import { writeErrorResponse } from "./sse-writer.js";
3
3
  import { applyChaosAsync } from "./chaos.js";
4
+ import { planMisbehavior, recordMisbehaviorOutcome } from "./misbehavior.js";
4
5
  import { matchFixtureDiagnostic, recordMatchOptions } from "./router.js";
5
6
  import { proxyAndRecord } from "./recorder.js";
6
7
  import { createInterruptionSignal } from "./interruption.js";
@@ -122,20 +123,8 @@ function buildOllamaChatTextResponse(content, model, reasoning) {
122
123
  ...DURATION_FIELDS
123
124
  };
124
125
  }
125
- function buildOllamaChatToolCallChunks(toolCalls, model, chunkSize, logger, reasoning) {
126
- const ollamaToolCalls = toolCalls.map((tc) => {
127
- let argsObj;
128
- try {
129
- argsObj = JSON.parse(tc.arguments || "{}");
130
- } catch {
131
- logger.warn(`Malformed JSON in fixture tool call arguments for "${tc.name}": ${tc.arguments}`);
132
- argsObj = {};
133
- }
134
- return { function: {
135
- name: tc.name,
136
- arguments: argsObj
137
- } };
138
- });
126
+ function buildOllamaChatToolCallChunks(toolCalls, model, chunkSize, reasoning) {
127
+ const ollamaToolCalls = toolCalls.map(toOllamaToolCall);
139
128
  const chunks = [];
140
129
  const createdAt = (/* @__PURE__ */ new Date()).toISOString();
141
130
  if (reasoning) for (let i = 0; i < reasoning.length; i += chunkSize) {
@@ -173,20 +162,8 @@ function buildOllamaChatToolCallChunks(toolCalls, model, chunkSize, logger, reas
173
162
  });
174
163
  return chunks;
175
164
  }
176
- function buildOllamaChatToolCallResponse(toolCalls, model, logger, reasoning) {
177
- const ollamaToolCalls = toolCalls.map((tc) => {
178
- let argsObj;
179
- try {
180
- argsObj = JSON.parse(tc.arguments || "{}");
181
- } catch {
182
- logger.warn(`Malformed JSON in fixture tool call arguments for "${tc.name}": ${tc.arguments}`);
183
- argsObj = {};
184
- }
185
- return { function: {
186
- name: tc.name,
187
- arguments: argsObj
188
- } };
189
- });
165
+ function buildOllamaChatToolCallResponse(toolCalls, model, reasoning) {
166
+ const ollamaToolCalls = toolCalls.map(toOllamaToolCall);
190
167
  return {
191
168
  model,
192
169
  created_at: (/* @__PURE__ */ new Date()).toISOString(),
@@ -200,20 +177,13 @@ function buildOllamaChatToolCallResponse(toolCalls, model, logger, reasoning) {
200
177
  ...DURATION_FIELDS
201
178
  };
202
179
  }
203
- function toOllamaToolCall(tc, logger) {
204
- let argsObj;
205
- try {
206
- argsObj = JSON.parse(tc.arguments || "{}");
207
- } catch {
208
- logger.warn(`Malformed JSON in fixture tool call arguments for "${tc.name}": ${tc.arguments}`);
209
- argsObj = {};
210
- }
180
+ function toOllamaToolCall(tc) {
211
181
  return { function: {
212
182
  name: tc.name,
213
- arguments: argsObj
183
+ arguments: servedToolArgs(tc, "object").value
214
184
  } };
215
185
  }
216
- function buildOllamaChatContentWithToolCallsChunks(content, toolCalls, model, chunkSize, logger, reasoning, blocks) {
186
+ function buildOllamaChatContentWithToolCallsChunks(content, toolCalls, model, chunkSize, reasoning, blocks) {
217
187
  const chunks = [];
218
188
  const createdAt = (/* @__PURE__ */ new Date()).toISOString();
219
189
  if (blocks && blocks.length > 0) {
@@ -249,7 +219,7 @@ function buildOllamaChatContentWithToolCallsChunks(content, toolCalls, model, ch
249
219
  message: {
250
220
  role: "assistant",
251
221
  content: "",
252
- tool_calls: [toOllamaToolCall(block, logger)]
222
+ tool_calls: [toOllamaToolCall(block)]
253
223
  },
254
224
  done: false
255
225
  });
@@ -290,19 +260,7 @@ function buildOllamaChatContentWithToolCallsChunks(content, toolCalls, model, ch
290
260
  done: false
291
261
  });
292
262
  }
293
- const ollamaToolCalls = toolCalls.map((tc) => {
294
- let argsObj;
295
- try {
296
- argsObj = JSON.parse(tc.arguments || "{}");
297
- } catch {
298
- logger.warn(`Malformed JSON in fixture tool call arguments for "${tc.name}": ${tc.arguments}`);
299
- argsObj = {};
300
- }
301
- return { function: {
302
- name: tc.name,
303
- arguments: argsObj
304
- } };
305
- });
263
+ const ollamaToolCalls = toolCalls.map(toOllamaToolCall);
306
264
  chunks.push({
307
265
  model,
308
266
  created_at: createdAt,
@@ -325,7 +283,7 @@ function buildOllamaChatContentWithToolCallsChunks(content, toolCalls, model, ch
325
283
  });
326
284
  return chunks;
327
285
  }
328
- function buildOllamaChatContentWithToolCallsResponse(content, toolCalls, model, logger, reasoning, blocks) {
286
+ function buildOllamaChatContentWithToolCallsResponse(content, toolCalls, model, reasoning, blocks) {
329
287
  if (blocks && blocks.length > 0) {
330
288
  const ordered = resolveFixtureBlocks(blocks);
331
289
  content = ordered.filter((b) => b.type === "text").map((b) => b.text).join("");
@@ -334,19 +292,7 @@ function buildOllamaChatContentWithToolCallsResponse(content, toolCalls, model,
334
292
  arguments: b.arguments
335
293
  }));
336
294
  }
337
- const ollamaToolCalls = toolCalls.map((tc) => {
338
- let argsObj;
339
- try {
340
- argsObj = JSON.parse(tc.arguments || "{}");
341
- } catch {
342
- logger.warn(`Malformed JSON in fixture tool call arguments for "${tc.name}": ${tc.arguments}`);
343
- argsObj = {};
344
- }
345
- return { function: {
346
- name: tc.name,
347
- arguments: argsObj
348
- } };
349
- });
295
+ const ollamaToolCalls = toolCalls.map(toOllamaToolCall);
350
296
  return {
351
297
  model,
352
298
  created_at: (/* @__PURE__ */ new Date()).toISOString(),
@@ -360,6 +306,105 @@ function buildOllamaChatContentWithToolCallsResponse(content, toolCalls, model,
360
306
  ...DURATION_FIELDS
361
307
  };
362
308
  }
309
+ /** Prepare fault output and its observations together before sending any bytes. */
310
+ function prepareOllamaMisbehavior(plan, request, stream, chunkSize, effectiveStrict, logger) {
311
+ const response = plan.response;
312
+ const combined = isCombinedFixtureResponse(response);
313
+ const outcome = combined && response.blocks?.length ? resolveFixtureBlockOutcome(response.blocks) : void 0;
314
+ const calls = outcome?.toolCalls ?? (combined || isToolCallResponse(response) ? response.toolCalls ?? [] : []);
315
+ const content = outcome?.content ?? ("content" in response ? response.content ?? "" : "");
316
+ const model = request.model;
317
+ if (plan.summary.fault === "tool-args-invalid-json") {
318
+ const target = calls[plan.target?.index ?? 0];
319
+ if (!target || toolArgsForWire(target).kind !== "verbatim") throw new Error("Ollama invalid-JSON fault requires an invalid prepared target");
320
+ const diagnostic = new InvalidToolArgumentsError(target).parseDiagnostic;
321
+ const error = `error parsing tool call: raw='${target.arguments}', err=${diagnostic}`;
322
+ let priorContent = content;
323
+ if (outcome) {
324
+ priorContent = "";
325
+ let index = 0;
326
+ for (const block of outcome.ordered) if (block.type === "text") priorContent += block.text;
327
+ else if (index++ === plan.target?.index) break;
328
+ }
329
+ return {
330
+ chunks: stream ? [...buildOllamaChatTextChunks(priorContent, model, chunkSize).slice(0, -1), { error }] : [{ error }],
331
+ status: stream ? 200 : 500,
332
+ summary: {
333
+ ...plan.summary,
334
+ servedToolCalls: []
335
+ }
336
+ };
337
+ }
338
+ const servedToolCalls = calls.map((call) => {
339
+ const parsed = toolArgsForWire(call);
340
+ if (parsed.kind === "verbatim") throw new InvalidToolArgumentsError(call);
341
+ return {
342
+ name: call.name,
343
+ arguments: parsed.text
344
+ };
345
+ });
346
+ let chunks;
347
+ let reasoning = "";
348
+ if (plan.summary.fault === "reasoning-only") {
349
+ reasoning = plan.reasoning ?? "";
350
+ const base = {
351
+ model,
352
+ created_at: (/* @__PURE__ */ new Date()).toISOString()
353
+ };
354
+ if (stream) {
355
+ chunks = [];
356
+ for (let i = 0; i < reasoning.length; i += chunkSize) chunks.push({
357
+ ...base,
358
+ message: {
359
+ role: "assistant",
360
+ content: "",
361
+ thinking: reasoning.slice(i, i + chunkSize)
362
+ },
363
+ done: false
364
+ });
365
+ chunks.push({
366
+ ...base,
367
+ message: {
368
+ role: "assistant",
369
+ content: ""
370
+ },
371
+ done: true,
372
+ ...DURATION_FIELDS,
373
+ done_reason: "length"
374
+ });
375
+ } else chunks = [{
376
+ ...base,
377
+ message: {
378
+ role: "assistant",
379
+ content: "",
380
+ thinking: reasoning
381
+ },
382
+ done: true,
383
+ ...DURATION_FIELDS,
384
+ done_reason: "length"
385
+ }];
386
+ } else {
387
+ reasoning = resolveReasoningForModel("reasoning" in response ? response.reasoning : void 0, model, effectiveStrict, logger) ?? "";
388
+ if (combined) chunks = stream ? buildOllamaChatContentWithToolCallsChunks(content, calls, model, chunkSize, reasoning, response.blocks) : [buildOllamaChatContentWithToolCallsResponse(content, calls, model, reasoning, response.blocks)];
389
+ else if (isToolCallResponse(response)) chunks = stream ? buildOllamaChatToolCallChunks(calls, model, chunkSize, reasoning) : [buildOllamaChatToolCallResponse(calls, model, reasoning)];
390
+ else chunks = stream ? buildOllamaChatTextChunks(content, model, chunkSize, reasoning) : [buildOllamaChatTextResponse(content, model, reasoning)];
391
+ }
392
+ const completion = content + reasoning + servedToolCalls.map((call) => call.name + call.arguments).join("");
393
+ const terminal = chunks.length - 1;
394
+ chunks[terminal] = {
395
+ ...chunks[terminal],
396
+ prompt_eval_count: estimatePromptTokens(request.messages),
397
+ eval_count: estimateTokens(completion)
398
+ };
399
+ return {
400
+ chunks,
401
+ status: 200,
402
+ summary: {
403
+ ...plan.summary,
404
+ servedToolCalls
405
+ }
406
+ };
407
+ }
363
408
  function buildOllamaGenerateTextChunks(content, model, chunkSize, reasoning) {
364
409
  const chunks = [];
365
410
  const createdAt = (/* @__PURE__ */ new Date()).toISOString();
@@ -445,7 +490,11 @@ async function handleOllama(req, res, raw, fixtures, journal, defaults, setCorsH
445
490
  } }));
446
491
  return;
447
492
  }
448
- const chatShapeError = validateChatMessages(ollamaReq.messages) ?? validateToolsField(ollamaReq.tools);
493
+ let chatShapeError = validateChatMessages(ollamaReq.messages) ?? validateToolsField(ollamaReq.tools);
494
+ if (!chatShapeError && Array.isArray(ollamaReq.tools)) {
495
+ const missingFunctionIndex = ollamaReq.tools.findIndex((tool) => tool.function === null || tool.function === void 0);
496
+ if (missingFunctionIndex !== -1) chatShapeError = `tools[${missingFunctionIndex}].function must be an object`;
497
+ }
449
498
  if (chatShapeError) {
450
499
  journal.add({
451
500
  method: req.method ?? "POST",
@@ -536,25 +585,100 @@ async function handleOllama(req, res, raw, fixtures, journal, defaults, setCorsH
536
585
  return;
537
586
  }
538
587
  const response = await resolveResponse(fixture, completionReq);
588
+ const misbehavior = planMisbehavior({
589
+ wire: "ollama",
590
+ fixture,
591
+ response,
592
+ request: completionReq,
593
+ stream: ollamaReq.stream !== false,
594
+ defaults,
595
+ rawHeaders: req.headers,
596
+ url: req.url
597
+ });
598
+ if (misbehavior.kind === "error") {
599
+ recordMisbehaviorOutcome({
600
+ entry: journal.add({
601
+ method: req.method ?? "POST",
602
+ path: urlPath,
603
+ headers: flattenHeaders(req.headers),
604
+ body: completionReq,
605
+ response: {
606
+ status: misbehavior.status,
607
+ fixture
608
+ }
609
+ }),
610
+ summary: misbehavior.summary,
611
+ defaults,
612
+ testId
613
+ });
614
+ const message = `${misbehavior.code}: ${misbehavior.message}`;
615
+ if (!misbehavior.summary?.evaluations.length) defaults.logger.error(message);
616
+ writeErrorResponse(res, misbehavior.status, JSON.stringify({ error: message }));
617
+ return;
618
+ }
539
619
  const latency = fixture.latency ?? defaults.latency;
540
620
  const chunkSize = Math.max(1, fixture.chunkSize ?? defaults.chunkSize);
541
621
  const streaming = ollamaReq.stream !== false;
542
- if (isErrorResponse(response)) {
543
- const status = response.status ?? 500;
544
- journal.add({
622
+ if (misbehavior.kind === "applied") {
623
+ const prepared = prepareOllamaMisbehavior(misbehavior, completionReq, streaming, chunkSize, resolveStrictMode(defaults.strict, req.headers), logger);
624
+ const journalEntry = journal.add({
545
625
  method: req.method ?? "POST",
546
626
  path: urlPath,
547
627
  headers: flattenHeaders(req.headers),
548
628
  body: completionReq,
549
629
  response: {
550
- status,
630
+ status: prepared.status,
551
631
  fixture
552
632
  }
553
633
  });
634
+ recordMisbehaviorOutcome({
635
+ entry: journalEntry,
636
+ summary: prepared.summary,
637
+ defaults,
638
+ testId
639
+ });
640
+ if (!streaming) {
641
+ res.writeHead(prepared.status, { "Content-Type": "application/json" });
642
+ res.end(JSON.stringify(prepared.chunks[0]));
643
+ } else {
644
+ const interruption = createInterruptionSignal(fixture);
645
+ if (!await writeNDJSONStream(res, prepared.chunks, {
646
+ latency,
647
+ streamingProfile: fixture.streamingProfile,
648
+ recordedTimings: fixture.recordedTimings,
649
+ replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed,
650
+ signal: interruption?.signal,
651
+ onChunkSent: interruption?.tick
652
+ })) {
653
+ if (!res.writableEnded) res.destroy();
654
+ journalEntry.response.interrupted = true;
655
+ journalEntry.response.interruptReason = interruption?.reason();
656
+ }
657
+ interruption?.cleanup();
658
+ }
659
+ return;
660
+ }
661
+ if (isErrorResponse(response)) {
662
+ const status = response.status ?? 500;
663
+ recordMisbehaviorOutcome({
664
+ entry: journal.add({
665
+ method: req.method ?? "POST",
666
+ path: urlPath,
667
+ headers: flattenHeaders(req.headers),
668
+ body: completionReq,
669
+ response: {
670
+ status,
671
+ fixture
672
+ }
673
+ }),
674
+ summary: misbehavior.summary,
675
+ defaults,
676
+ testId
677
+ });
554
678
  writeErrorResponse(res, status, serializeErrorResponse(response), { retryAfter: response.retryAfter });
555
679
  return;
556
680
  }
557
- if (isContentWithToolCallsResponse(response)) {
681
+ if (isCombinedFixtureResponse(response)) {
558
682
  if (response.webSearches?.length) logger.warn("webSearches in fixture response are not supported for Ollama API -- ignoring");
559
683
  const journalEntry = journal.add({
560
684
  method: req.method ?? "POST",
@@ -566,14 +690,21 @@ async function handleOllama(req, res, raw, fixtures, journal, defaults, setCorsH
566
690
  fixture
567
691
  }
568
692
  });
693
+ recordMisbehaviorOutcome({
694
+ entry: journalEntry,
695
+ summary: misbehavior.summary,
696
+ defaults,
697
+ testId
698
+ });
699
+ const functionToolCalls = requireEmittedFunctionToolCalls(response, "Ollama");
569
700
  const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);
570
701
  const effReasoning = resolveReasoningForModel(response.reasoning, completionReq.model, effectiveStrict, logger);
571
702
  if (!streaming) {
572
- const body = buildOllamaChatContentWithToolCallsResponse(response.content ?? "", response.toolCalls ?? [], completionReq.model, logger, effReasoning, response.blocks);
703
+ const body = buildOllamaChatContentWithToolCallsResponse(response.content ?? "", functionToolCalls, completionReq.model, effReasoning, response.blocks);
573
704
  res.writeHead(200, { "Content-Type": "application/json" });
574
705
  res.end(JSON.stringify(body));
575
706
  } else {
576
- const chunks = buildOllamaChatContentWithToolCallsChunks(response.content ?? "", response.toolCalls ?? [], completionReq.model, chunkSize, logger, effReasoning, response.blocks);
707
+ const chunks = buildOllamaChatContentWithToolCallsChunks(response.content ?? "", functionToolCalls, completionReq.model, chunkSize, effReasoning, response.blocks);
577
708
  const interruption = createInterruptionSignal(fixture);
578
709
  if (!await writeNDJSONStream(res, chunks, {
579
710
  latency,
@@ -603,6 +734,12 @@ async function handleOllama(req, res, raw, fixtures, journal, defaults, setCorsH
603
734
  fixture
604
735
  }
605
736
  });
737
+ recordMisbehaviorOutcome({
738
+ entry: journalEntry,
739
+ summary: misbehavior.summary,
740
+ defaults,
741
+ testId
742
+ });
606
743
  const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);
607
744
  const effReasoning = resolveReasoningForModel(response.reasoning, completionReq.model, effectiveStrict, logger);
608
745
  if (!streaming) {
@@ -640,14 +777,21 @@ async function handleOllama(req, res, raw, fixtures, journal, defaults, setCorsH
640
777
  fixture
641
778
  }
642
779
  });
780
+ recordMisbehaviorOutcome({
781
+ entry: journalEntry,
782
+ summary: misbehavior.summary,
783
+ defaults,
784
+ testId
785
+ });
786
+ const functionToolCalls = requireEmittedFunctionToolCalls(response, "Ollama");
643
787
  const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);
644
788
  const effReasoning = resolveReasoningForModel(response.reasoning, completionReq.model, effectiveStrict, logger);
645
789
  if (!streaming) {
646
- const body = buildOllamaChatToolCallResponse(response.toolCalls, completionReq.model, logger, effReasoning);
790
+ const body = buildOllamaChatToolCallResponse(functionToolCalls, completionReq.model, effReasoning);
647
791
  res.writeHead(200, { "Content-Type": "application/json" });
648
792
  res.end(JSON.stringify(body));
649
793
  } else {
650
- const chunks = buildOllamaChatToolCallChunks(response.toolCalls, completionReq.model, chunkSize, logger, effReasoning);
794
+ const chunks = buildOllamaChatToolCallChunks(functionToolCalls, completionReq.model, chunkSize, effReasoning);
651
795
  const interruption = createInterruptionSignal(fixture);
652
796
  if (!await writeNDJSONStream(res, chunks, {
653
797
  latency,
@@ -665,15 +809,20 @@ async function handleOllama(req, res, raw, fixtures, journal, defaults, setCorsH
665
809
  }
666
810
  return;
667
811
  }
668
- journal.add({
669
- method: req.method ?? "POST",
670
- path: urlPath,
671
- headers: flattenHeaders(req.headers),
672
- body: completionReq,
673
- response: {
674
- status: 500,
675
- fixture
676
- }
812
+ recordMisbehaviorOutcome({
813
+ entry: journal.add({
814
+ method: req.method ?? "POST",
815
+ path: urlPath,
816
+ headers: flattenHeaders(req.headers),
817
+ body: completionReq,
818
+ response: {
819
+ status: 500,
820
+ fixture
821
+ }
822
+ }),
823
+ summary: misbehavior.summary,
824
+ defaults,
825
+ testId
677
826
  });
678
827
  writeErrorResponse(res, 500, JSON.stringify({ error: {
679
828
  message: "Fixture response did not match any known type",
@@ -811,20 +960,57 @@ async function handleOllamaGenerate(req, res, raw, fixtures, journal, defaults,
811
960
  return;
812
961
  }
813
962
  const response = await resolveResponse(fixture, completionReq);
963
+ const misbehavior = planMisbehavior({
964
+ wire: "ollama",
965
+ faultRenderingAvailable: false,
966
+ fixture,
967
+ response,
968
+ request: completionReq,
969
+ stream: generateReq.stream !== false,
970
+ defaults,
971
+ rawHeaders: req.headers,
972
+ url: req.url
973
+ });
974
+ if (misbehavior.kind === "error") {
975
+ recordMisbehaviorOutcome({
976
+ entry: journal.add({
977
+ method: req.method ?? "POST",
978
+ path: urlPath,
979
+ headers: flattenHeaders(req.headers),
980
+ body: completionReq,
981
+ response: {
982
+ status: misbehavior.status,
983
+ fixture
984
+ }
985
+ }),
986
+ summary: misbehavior.summary,
987
+ defaults,
988
+ testId
989
+ });
990
+ const message = `${misbehavior.code}: ${misbehavior.message}`;
991
+ if (!misbehavior.summary?.evaluations.length) defaults.logger.error(message);
992
+ writeErrorResponse(res, misbehavior.status, JSON.stringify({ error: message }));
993
+ return;
994
+ }
814
995
  const latency = fixture.latency ?? defaults.latency;
815
996
  const chunkSize = Math.max(1, fixture.chunkSize ?? defaults.chunkSize);
816
997
  const streaming = generateReq.stream !== false;
817
998
  if (isErrorResponse(response)) {
818
999
  const status = response.status ?? 500;
819
- journal.add({
820
- method: req.method ?? "POST",
821
- path: urlPath,
822
- headers: flattenHeaders(req.headers),
823
- body: completionReq,
824
- response: {
825
- status,
826
- fixture
827
- }
1000
+ recordMisbehaviorOutcome({
1001
+ entry: journal.add({
1002
+ method: req.method ?? "POST",
1003
+ path: urlPath,
1004
+ headers: flattenHeaders(req.headers),
1005
+ body: completionReq,
1006
+ response: {
1007
+ status,
1008
+ fixture
1009
+ }
1010
+ }),
1011
+ summary: misbehavior.summary,
1012
+ defaults,
1013
+ testId
828
1014
  });
829
1015
  writeErrorResponse(res, status, serializeErrorResponse(response), { retryAfter: response.retryAfter });
830
1016
  return;
@@ -840,6 +1026,12 @@ async function handleOllamaGenerate(req, res, raw, fixtures, journal, defaults,
840
1026
  fixture
841
1027
  }
842
1028
  });
1029
+ recordMisbehaviorOutcome({
1030
+ entry: journalEntry,
1031
+ summary: misbehavior.summary,
1032
+ defaults,
1033
+ testId
1034
+ });
843
1035
  const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);
844
1036
  const effReasoning = resolveReasoningForModel(response.reasoning, completionReq.model, effectiveStrict, defaults.logger);
845
1037
  if (!streaming) {
@@ -865,16 +1057,21 @@ async function handleOllamaGenerate(req, res, raw, fixtures, journal, defaults,
865
1057
  }
866
1058
  return;
867
1059
  }
868
- if (isToolCallResponse(response) || isContentWithToolCallsResponse(response)) {
869
- journal.add({
870
- method: req.method ?? "POST",
871
- path: urlPath,
872
- headers: flattenHeaders(req.headers),
873
- body: completionReq,
874
- response: {
875
- status: 400,
876
- fixture
877
- }
1060
+ if (isToolCallResponse(response) || isCombinedFixtureResponse(response)) {
1061
+ recordMisbehaviorOutcome({
1062
+ entry: journal.add({
1063
+ method: req.method ?? "POST",
1064
+ path: urlPath,
1065
+ headers: flattenHeaders(req.headers),
1066
+ body: completionReq,
1067
+ response: {
1068
+ status: 400,
1069
+ fixture
1070
+ }
1071
+ }),
1072
+ summary: misbehavior.summary,
1073
+ defaults,
1074
+ testId
878
1075
  });
879
1076
  writeErrorResponse(res, 400, JSON.stringify({ error: {
880
1077
  message: "Tool call fixtures are not supported on /api/generate — use /api/chat instead",
@@ -882,15 +1079,20 @@ async function handleOllamaGenerate(req, res, raw, fixtures, journal, defaults,
882
1079
  } }));
883
1080
  return;
884
1081
  }
885
- journal.add({
886
- method: req.method ?? "POST",
887
- path: urlPath,
888
- headers: flattenHeaders(req.headers),
889
- body: completionReq,
890
- response: {
891
- status: 500,
892
- fixture
893
- }
1082
+ recordMisbehaviorOutcome({
1083
+ entry: journal.add({
1084
+ method: req.method ?? "POST",
1085
+ path: urlPath,
1086
+ headers: flattenHeaders(req.headers),
1087
+ body: completionReq,
1088
+ response: {
1089
+ status: 500,
1090
+ fixture
1091
+ }
1092
+ }),
1093
+ summary: misbehavior.summary,
1094
+ defaults,
1095
+ testId
894
1096
  });
895
1097
  writeErrorResponse(res, 500, JSON.stringify({ error: {
896
1098
  message: "Fixture response did not match any known type",