@copilotkit/aimock 1.45.1 → 1.47.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (492) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +25 -1
  4. package/README.md +11 -2
  5. package/dist/agui-mock.cjs +25 -25
  6. package/dist/agui-mock.cjs.map +1 -1
  7. package/dist/agui-mock.d.cts.map +1 -1
  8. package/dist/agui-mock.d.ts.map +1 -1
  9. package/dist/agui-mock.js +25 -25
  10. package/dist/agui-mock.js.map +1 -1
  11. package/dist/agui-types.d.cts.map +1 -1
  12. package/dist/aimock-cli.cjs +15 -1
  13. package/dist/aimock-cli.cjs.map +1 -1
  14. package/dist/aimock-cli.d.cts.map +1 -1
  15. package/dist/aimock-cli.d.ts.map +1 -1
  16. package/dist/aimock-cli.js +16 -2
  17. package/dist/aimock-cli.js.map +1 -1
  18. package/dist/api-key-auth.cjs +10 -9
  19. package/dist/api-key-auth.cjs.map +1 -1
  20. package/dist/api-key-auth.d.cts.map +1 -1
  21. package/dist/api-key-auth.d.ts.map +1 -1
  22. package/dist/api-key-auth.js +11 -10
  23. package/dist/api-key-auth.js.map +1 -1
  24. package/dist/aws-event-stream.cjs +20 -23
  25. package/dist/aws-event-stream.cjs.map +1 -1
  26. package/dist/aws-event-stream.d.cts +0 -1
  27. package/dist/aws-event-stream.d.ts +0 -1
  28. package/dist/aws-event-stream.js +20 -24
  29. package/dist/aws-event-stream.js.map +1 -1
  30. package/dist/batches.cjs +2 -4
  31. package/dist/batches.cjs.map +1 -1
  32. package/dist/batches.d.cts.map +1 -1
  33. package/dist/batches.d.ts.map +1 -1
  34. package/dist/batches.js +2 -4
  35. package/dist/batches.js.map +1 -1
  36. package/dist/bedrock-converse.cjs +139 -161
  37. package/dist/bedrock-converse.cjs.map +1 -1
  38. package/dist/bedrock-converse.d.cts.map +1 -1
  39. package/dist/bedrock-converse.d.ts.map +1 -1
  40. package/dist/bedrock-converse.js +137 -159
  41. package/dist/bedrock-converse.js.map +1 -1
  42. package/dist/bedrock.cjs +175 -216
  43. package/dist/bedrock.cjs.map +1 -1
  44. package/dist/bedrock.d.cts.map +1 -1
  45. package/dist/bedrock.d.ts.map +1 -1
  46. package/dist/bedrock.js +172 -213
  47. package/dist/bedrock.js.map +1 -1
  48. package/dist/byteplus-video.cjs +11 -10
  49. package/dist/byteplus-video.cjs.map +1 -1
  50. package/dist/byteplus-video.d.cts.map +1 -1
  51. package/dist/byteplus-video.d.ts.map +1 -1
  52. package/dist/byteplus-video.js +5 -4
  53. package/dist/byteplus-video.js.map +1 -1
  54. package/dist/chaos.cjs +5 -4
  55. package/dist/chaos.cjs.map +1 -1
  56. package/dist/chaos.d.cts.map +1 -1
  57. package/dist/chaos.d.ts.map +1 -1
  58. package/dist/chaos.js +5 -4
  59. package/dist/chaos.js.map +1 -1
  60. package/dist/cli.cjs +15 -0
  61. package/dist/cli.cjs.map +1 -1
  62. package/dist/cli.js +15 -0
  63. package/dist/cli.js.map +1 -1
  64. package/dist/cohere.cjs +107 -180
  65. package/dist/cohere.cjs.map +1 -1
  66. package/dist/cohere.d.cts.map +1 -1
  67. package/dist/cohere.d.ts.map +1 -1
  68. package/dist/cohere.js +106 -179
  69. package/dist/cohere.js.map +1 -1
  70. package/dist/config-loader.cjs +29 -1
  71. package/dist/config-loader.cjs.map +1 -1
  72. package/dist/config-loader.d.cts +7 -1
  73. package/dist/config-loader.d.cts.map +1 -1
  74. package/dist/config-loader.d.ts +7 -1
  75. package/dist/config-loader.d.ts.map +1 -1
  76. package/dist/config-loader.js +29 -2
  77. package/dist/config-loader.js.map +1 -1
  78. package/dist/count-tokens.cjs +146 -0
  79. package/dist/count-tokens.cjs.map +1 -0
  80. package/dist/count-tokens.js +146 -0
  81. package/dist/count-tokens.js.map +1 -0
  82. package/dist/elevenlabs-audio.cjs +36 -34
  83. package/dist/elevenlabs-audio.cjs.map +1 -1
  84. package/dist/elevenlabs-audio.d.cts.map +1 -1
  85. package/dist/elevenlabs-audio.d.ts.map +1 -1
  86. package/dist/elevenlabs-audio.js +33 -31
  87. package/dist/elevenlabs-audio.js.map +1 -1
  88. package/dist/elevenlabs-voice.cjs +38 -37
  89. package/dist/elevenlabs-voice.cjs.map +1 -1
  90. package/dist/elevenlabs-voice.d.cts.map +1 -1
  91. package/dist/elevenlabs-voice.d.ts.map +1 -1
  92. package/dist/elevenlabs-voice.js +33 -32
  93. package/dist/elevenlabs-voice.js.map +1 -1
  94. package/dist/embedding-request.cjs +16 -0
  95. package/dist/embedding-request.cjs.map +1 -0
  96. package/dist/embedding-request.js +14 -0
  97. package/dist/embedding-request.js.map +1 -0
  98. package/dist/embeddings.cjs +30 -20
  99. package/dist/embeddings.cjs.map +1 -1
  100. package/dist/embeddings.d.cts.map +1 -1
  101. package/dist/embeddings.d.ts.map +1 -1
  102. package/dist/embeddings.js +30 -20
  103. package/dist/embeddings.js.map +1 -1
  104. package/dist/fal-audio.cjs +45 -43
  105. package/dist/fal-audio.cjs.map +1 -1
  106. package/dist/fal-audio.d.cts.map +1 -1
  107. package/dist/fal-audio.d.ts.map +1 -1
  108. package/dist/fal-audio.js +42 -40
  109. package/dist/fal-audio.js.map +1 -1
  110. package/dist/fal.cjs +17 -15
  111. package/dist/fal.cjs.map +1 -1
  112. package/dist/fal.js +16 -14
  113. package/dist/fal.js.map +1 -1
  114. package/dist/files.cjs +2 -4
  115. package/dist/files.cjs.map +1 -1
  116. package/dist/files.d.cts.map +1 -1
  117. package/dist/files.d.ts.map +1 -1
  118. package/dist/files.js +2 -4
  119. package/dist/files.js.map +1 -1
  120. package/dist/fine-tuning.cjs +2 -4
  121. package/dist/fine-tuning.cjs.map +1 -1
  122. package/dist/fine-tuning.d.cts.map +1 -1
  123. package/dist/fine-tuning.d.ts.map +1 -1
  124. package/dist/fine-tuning.js +2 -4
  125. package/dist/fine-tuning.js.map +1 -1
  126. package/dist/fixture-loader.cjs +140 -44
  127. package/dist/fixture-loader.cjs.map +1 -1
  128. package/dist/fixture-loader.d.cts.map +1 -1
  129. package/dist/fixture-loader.d.ts.map +1 -1
  130. package/dist/fixture-loader.js +141 -46
  131. package/dist/fixture-loader.js.map +1 -1
  132. package/dist/gemini-embeddings.cjs +26 -24
  133. package/dist/gemini-embeddings.cjs.map +1 -1
  134. package/dist/gemini-embeddings.js +26 -24
  135. package/dist/gemini-embeddings.js.map +1 -1
  136. package/dist/gemini-interactions.cjs +113 -156
  137. package/dist/gemini-interactions.cjs.map +1 -1
  138. package/dist/gemini-interactions.d.cts +0 -1
  139. package/dist/gemini-interactions.d.cts.map +1 -1
  140. package/dist/gemini-interactions.d.ts +0 -1
  141. package/dist/gemini-interactions.d.ts.map +1 -1
  142. package/dist/gemini-interactions.js +113 -156
  143. package/dist/gemini-interactions.js.map +1 -1
  144. package/dist/gemini.cjs +295 -218
  145. package/dist/gemini.cjs.map +1 -1
  146. package/dist/gemini.d.cts.map +1 -1
  147. package/dist/gemini.d.ts.map +1 -1
  148. package/dist/gemini.js +295 -219
  149. package/dist/gemini.js.map +1 -1
  150. package/dist/grok-video.cjs +14 -12
  151. package/dist/grok-video.cjs.map +1 -1
  152. package/dist/grok-video.d.cts.map +1 -1
  153. package/dist/grok-video.d.ts.map +1 -1
  154. package/dist/grok-video.js +8 -6
  155. package/dist/grok-video.js.map +1 -1
  156. package/dist/helpers.cjs +411 -75
  157. package/dist/helpers.cjs.map +1 -1
  158. package/dist/helpers.d.cts +51 -1
  159. package/dist/helpers.d.cts.map +1 -1
  160. package/dist/helpers.d.ts +51 -1
  161. package/dist/helpers.d.ts.map +1 -1
  162. package/dist/helpers.js +402 -74
  163. package/dist/helpers.js.map +1 -1
  164. package/dist/images.cjs +30 -28
  165. package/dist/images.cjs.map +1 -1
  166. package/dist/images.d.cts.map +1 -1
  167. package/dist/images.d.ts.map +1 -1
  168. package/dist/images.js +27 -25
  169. package/dist/images.js.map +1 -1
  170. package/dist/index.cjs +4 -2
  171. package/dist/index.d.cts +4 -4
  172. package/dist/index.d.ts +4 -4
  173. package/dist/index.js +4 -4
  174. package/dist/journal.cjs +3 -1
  175. package/dist/journal.cjs.map +1 -1
  176. package/dist/journal.d.cts.map +1 -1
  177. package/dist/journal.d.ts.map +1 -1
  178. package/dist/journal.js +2 -1
  179. package/dist/journal.js.map +1 -1
  180. package/dist/llmock.cjs +3 -0
  181. package/dist/llmock.cjs.map +1 -1
  182. package/dist/llmock.d.cts.map +1 -1
  183. package/dist/llmock.d.ts.map +1 -1
  184. package/dist/llmock.js +3 -0
  185. package/dist/llmock.js.map +1 -1
  186. package/dist/mcp-fakes.d.cts.map +1 -1
  187. package/dist/mcp-handler.cjs +7 -3
  188. package/dist/mcp-handler.cjs.map +1 -1
  189. package/dist/mcp-handler.js +7 -3
  190. package/dist/mcp-handler.js.map +1 -1
  191. package/dist/mcp-recorder.cjs +2 -1
  192. package/dist/mcp-recorder.cjs.map +1 -1
  193. package/dist/mcp-recorder.js +3 -2
  194. package/dist/mcp-recorder.js.map +1 -1
  195. package/dist/messages.cjs +235 -202
  196. package/dist/messages.cjs.map +1 -1
  197. package/dist/messages.d.cts.map +1 -1
  198. package/dist/messages.d.ts.map +1 -1
  199. package/dist/messages.js +234 -202
  200. package/dist/messages.js.map +1 -1
  201. package/dist/metrics.cjs +5 -2
  202. package/dist/metrics.cjs.map +1 -1
  203. package/dist/metrics.d.cts.map +1 -1
  204. package/dist/metrics.d.ts.map +1 -1
  205. package/dist/metrics.js +6 -3
  206. package/dist/metrics.js.map +1 -1
  207. package/dist/misbehavior.cjs +62 -3
  208. package/dist/misbehavior.cjs.map +1 -1
  209. package/dist/misbehavior.d.cts.map +1 -1
  210. package/dist/misbehavior.d.ts.map +1 -1
  211. package/dist/misbehavior.js +63 -4
  212. package/dist/misbehavior.js.map +1 -1
  213. package/dist/model-utils.cjs +1 -0
  214. package/dist/model-utils.cjs.map +1 -1
  215. package/dist/model-utils.js +1 -1
  216. package/dist/model-utils.js.map +1 -1
  217. package/dist/moderation.cjs +15 -12
  218. package/dist/moderation.cjs.map +1 -1
  219. package/dist/moderation.js +14 -11
  220. package/dist/moderation.js.map +1 -1
  221. package/dist/ndjson-writer.cjs +21 -23
  222. package/dist/ndjson-writer.cjs.map +1 -1
  223. package/dist/ndjson-writer.d.cts +0 -1
  224. package/dist/ndjson-writer.d.cts.map +1 -1
  225. package/dist/ndjson-writer.d.ts +0 -1
  226. package/dist/ndjson-writer.d.ts.map +1 -1
  227. package/dist/ndjson-writer.js +21 -24
  228. package/dist/ndjson-writer.js.map +1 -1
  229. package/dist/ollama.cjs +276 -210
  230. package/dist/ollama.cjs.map +1 -1
  231. package/dist/ollama.d.cts.map +1 -1
  232. package/dist/ollama.d.ts.map +1 -1
  233. package/dist/ollama.js +273 -207
  234. package/dist/ollama.js.map +1 -1
  235. package/dist/openapi.cjs +323 -3
  236. package/dist/openapi.cjs.map +1 -1
  237. package/dist/openapi.d.cts.map +1 -1
  238. package/dist/openapi.d.ts.map +1 -1
  239. package/dist/openapi.js +324 -4
  240. package/dist/openapi.js.map +1 -1
  241. package/dist/openrouter-chat.cjs +11 -155
  242. package/dist/openrouter-chat.cjs.map +1 -1
  243. package/dist/openrouter-chat.js +11 -155
  244. package/dist/openrouter-chat.js.map +1 -1
  245. package/dist/openrouter-video.cjs +51 -74
  246. package/dist/openrouter-video.cjs.map +1 -1
  247. package/dist/openrouter-video.d.cts.map +1 -1
  248. package/dist/openrouter-video.d.ts.map +1 -1
  249. package/dist/openrouter-video.js +37 -60
  250. package/dist/openrouter-video.js.map +1 -1
  251. package/dist/raw-validation.cjs +177 -0
  252. package/dist/raw-validation.cjs.map +1 -0
  253. package/dist/raw-validation.js +176 -0
  254. package/dist/raw-validation.js.map +1 -0
  255. package/dist/recorder.cjs +176 -95
  256. package/dist/recorder.cjs.map +1 -1
  257. package/dist/recorder.d.cts.map +1 -1
  258. package/dist/recorder.d.ts.map +1 -1
  259. package/dist/recorder.js +176 -95
  260. package/dist/recorder.js.map +1 -1
  261. package/dist/rerank.cjs +13 -11
  262. package/dist/rerank.cjs.map +1 -1
  263. package/dist/rerank.js +12 -10
  264. package/dist/rerank.js.map +1 -1
  265. package/dist/response/catalog/anthropic-page.cjs +39 -0
  266. package/dist/response/catalog/anthropic-page.cjs.map +1 -0
  267. package/dist/response/catalog/anthropic-page.js +38 -0
  268. package/dist/response/catalog/anthropic-page.js.map +1 -0
  269. package/dist/response/catalog/collect.cjs +61 -0
  270. package/dist/response/catalog/collect.cjs.map +1 -0
  271. package/dist/response/catalog/collect.js +59 -0
  272. package/dist/response/catalog/collect.js.map +1 -0
  273. package/dist/response/catalog/gemini-page.cjs +25 -0
  274. package/dist/response/catalog/gemini-page.cjs.map +1 -0
  275. package/dist/response/catalog/gemini-page.js +24 -0
  276. package/dist/response/catalog/gemini-page.js.map +1 -0
  277. package/dist/response/catalog/render.cjs +182 -0
  278. package/dist/response/catalog/render.cjs.map +1 -0
  279. package/dist/response/catalog/render.js +171 -0
  280. package/dist/response/catalog/render.js.map +1 -0
  281. package/dist/response/deliver.cjs +144 -0
  282. package/dist/response/deliver.cjs.map +1 -0
  283. package/dist/response/deliver.js +143 -0
  284. package/dist/response/deliver.js.map +1 -0
  285. package/dist/response/errors.cjs +225 -0
  286. package/dist/response/errors.cjs.map +1 -0
  287. package/dist/response/errors.js +224 -0
  288. package/dist/response/errors.js.map +1 -0
  289. package/dist/response/finish.cjs +39 -0
  290. package/dist/response/finish.cjs.map +1 -0
  291. package/dist/response/finish.js +35 -0
  292. package/dist/response/finish.js.map +1 -0
  293. package/dist/response/frame-loop.cjs +102 -0
  294. package/dist/response/frame-loop.cjs.map +1 -0
  295. package/dist/response/frame-loop.js +100 -0
  296. package/dist/response/frame-loop.js.map +1 -0
  297. package/dist/response/lifecycle.cjs +223 -0
  298. package/dist/response/lifecycle.cjs.map +1 -0
  299. package/dist/response/lifecycle.js +211 -0
  300. package/dist/response/lifecycle.js.map +1 -0
  301. package/dist/response/policy.cjs +126 -0
  302. package/dist/response/policy.cjs.map +1 -0
  303. package/dist/response/policy.js +120 -0
  304. package/dist/response/policy.js.map +1 -0
  305. package/dist/response/profiles.cjs +69 -0
  306. package/dist/response/profiles.cjs.map +1 -0
  307. package/dist/response/profiles.js +65 -0
  308. package/dist/response/profiles.js.map +1 -0
  309. package/dist/response/proxy.cjs +71 -0
  310. package/dist/response/proxy.cjs.map +1 -0
  311. package/dist/response/proxy.js +70 -0
  312. package/dist/response/proxy.js.map +1 -0
  313. package/dist/response/raw.cjs +228 -0
  314. package/dist/response/raw.cjs.map +1 -0
  315. package/dist/response/raw.js +227 -0
  316. package/dist/response/raw.js.map +1 -0
  317. package/dist/response/timing.cjs +157 -0
  318. package/dist/response/timing.cjs.map +1 -0
  319. package/dist/response/timing.js +150 -0
  320. package/dist/response/timing.js.map +1 -0
  321. package/dist/response/usage/codecs/anthropic.cjs +52 -0
  322. package/dist/response/usage/codecs/anthropic.cjs.map +1 -0
  323. package/dist/response/usage/codecs/anthropic.js +50 -0
  324. package/dist/response/usage/codecs/anthropic.js.map +1 -0
  325. package/dist/response/usage/codecs/cohere.cjs +36 -0
  326. package/dist/response/usage/codecs/cohere.cjs.map +1 -0
  327. package/dist/response/usage/codecs/cohere.js +35 -0
  328. package/dist/response/usage/codecs/cohere.js.map +1 -0
  329. package/dist/response/usage/codecs/converse.cjs +16 -0
  330. package/dist/response/usage/codecs/converse.cjs.map +1 -0
  331. package/dist/response/usage/codecs/converse.js +15 -0
  332. package/dist/response/usage/codecs/converse.js.map +1 -0
  333. package/dist/response/usage/codecs/gemini.cjs +31 -0
  334. package/dist/response/usage/codecs/gemini.cjs.map +1 -0
  335. package/dist/response/usage/codecs/gemini.js +31 -0
  336. package/dist/response/usage/codecs/gemini.js.map +1 -0
  337. package/dist/response/usage/codecs/interactions.cjs +22 -0
  338. package/dist/response/usage/codecs/interactions.cjs.map +1 -0
  339. package/dist/response/usage/codecs/interactions.js +21 -0
  340. package/dist/response/usage/codecs/interactions.js.map +1 -0
  341. package/dist/response/usage/codecs/ollama.cjs +17 -0
  342. package/dist/response/usage/codecs/ollama.cjs.map +1 -0
  343. package/dist/response/usage/codecs/ollama.js +17 -0
  344. package/dist/response/usage/codecs/ollama.js.map +1 -0
  345. package/dist/response/usage/codecs/openai.cjs +52 -0
  346. package/dist/response/usage/codecs/openai.cjs.map +1 -0
  347. package/dist/response/usage/codecs/openai.js +50 -0
  348. package/dist/response/usage/codecs/openai.js.map +1 -0
  349. package/dist/response/usage/codecs/openrouter.cjs +68 -0
  350. package/dist/response/usage/codecs/openrouter.cjs.map +1 -0
  351. package/dist/response/usage/codecs/openrouter.js +67 -0
  352. package/dist/response/usage/codecs/openrouter.js.map +1 -0
  353. package/dist/response/usage/codecs/realtime.cjs +19 -0
  354. package/dist/response/usage/codecs/realtime.cjs.map +1 -0
  355. package/dist/response/usage/codecs/realtime.js +18 -0
  356. package/dist/response/usage/codecs/realtime.js.map +1 -0
  357. package/dist/response/usage/codecs/responses.cjs +21 -0
  358. package/dist/response/usage/codecs/responses.cjs.map +1 -0
  359. package/dist/response/usage/codecs/responses.js +20 -0
  360. package/dist/response/usage/codecs/responses.js.map +1 -0
  361. package/dist/response/usage/estimate.cjs +23 -0
  362. package/dist/response/usage/estimate.cjs.map +1 -0
  363. package/dist/response/usage/estimate.js +21 -0
  364. package/dist/response/usage/estimate.js.map +1 -0
  365. package/dist/response/usage/fields.cjs +72 -0
  366. package/dist/response/usage/fields.cjs.map +1 -0
  367. package/dist/response/usage/fields.js +70 -0
  368. package/dist/response/usage/fields.js.map +1 -0
  369. package/dist/response/usage/recording.cjs +52 -0
  370. package/dist/response/usage/recording.cjs.map +1 -0
  371. package/dist/response/usage/recording.js +52 -0
  372. package/dist/response/usage/recording.js.map +1 -0
  373. package/dist/responses.cjs +304 -196
  374. package/dist/responses.cjs.map +1 -1
  375. package/dist/responses.d.cts.map +1 -1
  376. package/dist/responses.d.ts.map +1 -1
  377. package/dist/responses.js +303 -195
  378. package/dist/responses.js.map +1 -1
  379. package/dist/route-registry.cjs +45 -0
  380. package/dist/route-registry.cjs.map +1 -1
  381. package/dist/route-registry.d.cts.map +1 -1
  382. package/dist/route-registry.d.ts.map +1 -1
  383. package/dist/route-registry.js +41 -1
  384. package/dist/route-registry.js.map +1 -1
  385. package/dist/router.cjs +24 -4
  386. package/dist/router.cjs.map +1 -1
  387. package/dist/router.d.cts +7 -1
  388. package/dist/router.d.cts.map +1 -1
  389. package/dist/router.d.ts +7 -1
  390. package/dist/router.d.ts.map +1 -1
  391. package/dist/router.js +24 -5
  392. package/dist/router.js.map +1 -1
  393. package/dist/search.cjs +13 -11
  394. package/dist/search.cjs.map +1 -1
  395. package/dist/search.js +12 -10
  396. package/dist/search.js.map +1 -1
  397. package/dist/server.cjs +293 -248
  398. package/dist/server.cjs.map +1 -1
  399. package/dist/server.d.cts.map +1 -1
  400. package/dist/server.d.ts.map +1 -1
  401. package/dist/server.js +294 -249
  402. package/dist/server.js.map +1 -1
  403. package/dist/speech.cjs +20 -18
  404. package/dist/speech.cjs.map +1 -1
  405. package/dist/speech.d.cts.map +1 -1
  406. package/dist/speech.d.ts.map +1 -1
  407. package/dist/speech.js +19 -17
  408. package/dist/speech.js.map +1 -1
  409. package/dist/sse-writer.cjs +56 -30
  410. package/dist/sse-writer.cjs.map +1 -1
  411. package/dist/sse-writer.d.cts +0 -1
  412. package/dist/sse-writer.d.cts.map +1 -1
  413. package/dist/sse-writer.d.ts +0 -1
  414. package/dist/sse-writer.d.ts.map +1 -1
  415. package/dist/sse-writer.js +55 -31
  416. package/dist/sse-writer.js.map +1 -1
  417. package/dist/stream-collapse.cjs +118 -11
  418. package/dist/stream-collapse.cjs.map +1 -1
  419. package/dist/stream-collapse.d.cts +10 -9
  420. package/dist/stream-collapse.d.cts.map +1 -1
  421. package/dist/stream-collapse.d.ts +10 -9
  422. package/dist/stream-collapse.d.ts.map +1 -1
  423. package/dist/stream-collapse.js +118 -11
  424. package/dist/stream-collapse.js.map +1 -1
  425. package/dist/transcription.cjs +31 -43
  426. package/dist/transcription.cjs.map +1 -1
  427. package/dist/transcription.d.cts.map +1 -1
  428. package/dist/transcription.d.ts.map +1 -1
  429. package/dist/transcription.js +31 -43
  430. package/dist/transcription.js.map +1 -1
  431. package/dist/types.cjs.map +1 -1
  432. package/dist/types.d.cts +231 -9
  433. package/dist/types.d.cts.map +1 -1
  434. package/dist/types.d.ts +231 -9
  435. package/dist/types.d.ts.map +1 -1
  436. package/dist/types.js.map +1 -1
  437. package/dist/vector-mock.cjs +3 -8
  438. package/dist/vector-mock.cjs.map +1 -1
  439. package/dist/vector-mock.d.cts.map +1 -1
  440. package/dist/vector-mock.d.ts.map +1 -1
  441. package/dist/vector-mock.js +3 -8
  442. package/dist/vector-mock.js.map +1 -1
  443. package/dist/vector-stores.cjs +2 -4
  444. package/dist/vector-stores.cjs.map +1 -1
  445. package/dist/vector-stores.d.cts.map +1 -1
  446. package/dist/vector-stores.d.ts.map +1 -1
  447. package/dist/vector-stores.js +2 -4
  448. package/dist/vector-stores.js.map +1 -1
  449. package/dist/veo-video.cjs +16 -14
  450. package/dist/veo-video.cjs.map +1 -1
  451. package/dist/veo-video.js +10 -8
  452. package/dist/veo-video.js.map +1 -1
  453. package/dist/video.cjs +21 -19
  454. package/dist/video.cjs.map +1 -1
  455. package/dist/video.d.cts.map +1 -1
  456. package/dist/video.d.ts.map +1 -1
  457. package/dist/video.js +20 -18
  458. package/dist/video.js.map +1 -1
  459. package/dist/ws-framing.cjs +12 -6
  460. package/dist/ws-framing.cjs.map +1 -1
  461. package/dist/ws-framing.d.cts +2 -0
  462. package/dist/ws-framing.d.cts.map +1 -1
  463. package/dist/ws-framing.d.ts +2 -0
  464. package/dist/ws-framing.d.ts.map +1 -1
  465. package/dist/ws-framing.js +12 -6
  466. package/dist/ws-framing.js.map +1 -1
  467. package/dist/ws-gemini-live.cjs +131 -96
  468. package/dist/ws-gemini-live.cjs.map +1 -1
  469. package/dist/ws-gemini-live.d.cts +0 -1
  470. package/dist/ws-gemini-live.d.cts.map +1 -1
  471. package/dist/ws-gemini-live.d.ts +0 -1
  472. package/dist/ws-gemini-live.d.ts.map +1 -1
  473. package/dist/ws-gemini-live.js +130 -95
  474. package/dist/ws-gemini-live.js.map +1 -1
  475. package/dist/ws-live.cjs +6 -5
  476. package/dist/ws-live.cjs.map +1 -1
  477. package/dist/ws-live.js +5 -4
  478. package/dist/ws-live.js.map +1 -1
  479. package/dist/ws-realtime.cjs +108 -124
  480. package/dist/ws-realtime.cjs.map +1 -1
  481. package/dist/ws-realtime.d.cts.map +1 -1
  482. package/dist/ws-realtime.d.ts.map +1 -1
  483. package/dist/ws-realtime.js +105 -121
  484. package/dist/ws-realtime.js.map +1 -1
  485. package/dist/ws-responses.cjs +80 -59
  486. package/dist/ws-responses.cjs.map +1 -1
  487. package/dist/ws-responses.d.cts.map +1 -1
  488. package/dist/ws-responses.d.ts.map +1 -1
  489. package/dist/ws-responses.js +79 -58
  490. package/dist/ws-responses.js.map +1 -1
  491. package/package.json +4 -1
  492. package/skills/write-fixtures/SKILL.md +57 -16
package/dist/ollama.cjs CHANGED
@@ -1,20 +1,27 @@
1
+ const require_errors = require('./response/errors.cjs');
2
+ const require_policy = require('./response/policy.cjs');
1
3
  const require_helpers = require('./helpers.cjs');
2
4
  const require_sse_writer = require('./sse-writer.cjs');
3
5
  const require_chaos = require('./chaos.cjs');
4
6
  const require_misbehavior = require('./misbehavior.cjs');
7
+ const require_embedding_request = require('./embedding-request.cjs');
5
8
  const require_router = require('./router.cjs');
6
9
  const require_recorder = require('./recorder.cjs');
7
- const require_interruption = require('./interruption.cjs');
10
+ const require_timing = require('./response/timing.cjs');
11
+ const require_deliver = require('./response/deliver.cjs');
12
+ const require_proxy = require('./response/proxy.cjs');
8
13
  const require_ndjson_writer = require('./ndjson-writer.cjs');
14
+ const require_raw = require('./response/raw.cjs');
15
+ const require_ollama = require('./response/usage/codecs/ollama.cjs');
9
16
 
10
17
  //#region src/ollama.ts
11
18
  const DURATION_FIELDS = {
12
19
  done_reason: "stop",
13
20
  total_duration: 0,
14
21
  load_duration: 0,
15
- prompt_eval_count: 0,
22
+ ...require_ollama.render({ kind: "ordinary-zero" }, "prompt"),
16
23
  prompt_eval_duration: 0,
17
- eval_count: 0,
24
+ ...require_ollama.render({ kind: "ordinary-zero" }, "completion"),
18
25
  eval_duration: 0
19
26
  };
20
27
  function ollamaToCompletionRequest(req) {
@@ -326,8 +333,10 @@ function prepareOllamaMisbehavior(plan, request, stream, chunkSize, effectiveStr
326
333
  for (const block of outcome.ordered) if (block.type === "text") priorContent += block.text;
327
334
  else if (index++ === plan.target?.index) break;
328
335
  }
336
+ const chunks = stream ? [...buildOllamaChatTextChunks(priorContent, model, chunkSize).slice(0, -1), { error }] : [{ error }];
329
337
  return {
330
- chunks: stream ? [...buildOllamaChatTextChunks(priorContent, model, chunkSize).slice(0, -1), { error }] : [{ error }],
338
+ build: () => chunks,
339
+ reasoning: void 0,
331
340
  status: stream ? 200 : 500,
332
341
  summary: {
333
342
  ...plan.summary,
@@ -343,61 +352,64 @@ function prepareOllamaMisbehavior(plan, request, stream, chunkSize, effectiveStr
343
352
  arguments: parsed.text
344
353
  };
345
354
  });
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({
355
+ const reasoning = plan.summary.fault === "reasoning-only" ? plan.reasoning ?? "" : require_helpers.resolveReasoningForModel("reasoning" in response ? response.reasoning : void 0, model, effectiveStrict, logger) ?? "";
356
+ const completion = content + reasoning + servedToolCalls.map((call) => call.name + call.arguments).join("");
357
+ const build = () => {
358
+ let chunks;
359
+ if (plan.summary.fault === "reasoning-only") {
360
+ const base = {
361
+ model,
362
+ created_at: (/* @__PURE__ */ new Date()).toISOString()
363
+ };
364
+ if (stream) {
365
+ chunks = [];
366
+ for (let i = 0; i < reasoning.length; i += chunkSize) chunks.push({
367
+ ...base,
368
+ message: {
369
+ role: "assistant",
370
+ content: "",
371
+ thinking: reasoning.slice(i, i + chunkSize)
372
+ },
373
+ done: false
374
+ });
375
+ chunks.push({
376
+ ...base,
377
+ message: {
378
+ role: "assistant",
379
+ content: ""
380
+ },
381
+ done: true,
382
+ ...DURATION_FIELDS,
383
+ done_reason: "length"
384
+ });
385
+ } else chunks = [{
357
386
  ...base,
358
387
  message: {
359
388
  role: "assistant",
360
389
  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: ""
390
+ thinking: reasoning
370
391
  },
371
392
  done: true,
372
393
  ...DURATION_FIELDS,
373
394
  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 = require_helpers.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)];
395
+ }];
396
+ } else if (combined) chunks = stream ? buildOllamaChatContentWithToolCallsChunks(content, calls, model, chunkSize, reasoning, response.blocks) : [buildOllamaChatContentWithToolCallsResponse(content, calls, model, reasoning, response.blocks)];
389
397
  else if (require_helpers.isToolCallResponse(response)) chunks = stream ? buildOllamaChatToolCallChunks(calls, model, chunkSize, reasoning) : [buildOllamaChatToolCallResponse(calls, model, reasoning)];
390
398
  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: require_helpers.estimatePromptTokens(request.messages),
397
- eval_count: require_helpers.estimateTokens(completion)
399
+ const terminal = chunks.length - 1;
400
+ chunks[terminal] = {
401
+ ...chunks[terminal],
402
+ ...require_ollama.render({
403
+ kind: "applied-chat-estimate",
404
+ messages: request.messages,
405
+ completion
406
+ })
407
+ };
408
+ return chunks;
398
409
  };
399
410
  return {
400
- chunks,
411
+ build,
412
+ reasoning,
401
413
  status: 200,
402
414
  summary: {
403
415
  ...plan.summary,
@@ -467,10 +479,10 @@ async function handleOllama(req, res, raw, fixtures, journal, defaults, setCorsH
467
479
  fixture: null
468
480
  }
469
481
  });
470
- require_sse_writer.writeErrorResponse(res, 400, JSON.stringify({ error: {
482
+ require_sse_writer.writeErrorResponse(res, 400, require_errors.renderError("ollama", "validation", {
471
483
  message: `Malformed JSON body: ${detail}`,
472
484
  type: "invalid_request_error"
473
- } }));
485
+ }).body);
474
486
  return;
475
487
  }
476
488
  if (!require_helpers.isJsonObject(ollamaReq)) {
@@ -484,10 +496,10 @@ async function handleOllama(req, res, raw, fixtures, journal, defaults, setCorsH
484
496
  fixture: null
485
497
  }
486
498
  });
487
- require_sse_writer.writeErrorResponse(res, 400, JSON.stringify({ error: {
499
+ require_sse_writer.writeErrorResponse(res, 400, require_errors.renderError("ollama", "validation", {
488
500
  message: "Request body must be a JSON object",
489
501
  type: "invalid_request_error"
490
- } }));
502
+ }).body);
491
503
  return;
492
504
  }
493
505
  let chatShapeError = require_helpers.validateChatMessages(ollamaReq.messages) ?? require_helpers.validateToolsField(ollamaReq.tools);
@@ -506,17 +518,20 @@ async function handleOllama(req, res, raw, fixtures, journal, defaults, setCorsH
506
518
  fixture: null
507
519
  }
508
520
  });
509
- require_sse_writer.writeErrorResponse(res, 400, JSON.stringify({ error: {
521
+ require_sse_writer.writeErrorResponse(res, 400, require_errors.renderError("ollama", "validation", {
510
522
  message: `Invalid request: ${chatShapeError}`,
511
523
  type: "invalid_request_error"
512
- } }));
524
+ }).body);
513
525
  return;
514
526
  }
515
527
  const completionReq = ollamaToCompletionRequest(ollamaReq);
516
528
  completionReq._endpointType = "chat";
517
529
  completionReq._context = require_helpers.getContext(req);
518
530
  const testId = require_helpers.getTestId(req);
519
- const { fixture, skippedBySequenceOrTurn } = require_router.matchFixtureDiagnostic(fixtures, completionReq, journal.getFixtureMatchCountsForTest(testId), defaults.requestTransform, require_router.recordMatchOptions(!!defaults.record, defaults.logger));
531
+ const { fixture, skippedBySequenceOrTurn } = require_router.matchFixtureDiagnostic(fixtures, completionReq, journal.getFixtureMatchCountsForTest(testId), defaults.requestTransform, {
532
+ ...require_router.recordMatchOptions(!!defaults.record, defaults.logger),
533
+ wire: "ollama"
534
+ });
520
535
  if (fixture) {
521
536
  journal.incrementFixtureMatchCount(fixture, fixtures, testId);
522
537
  logger.debug(`Fixture matched: ${JSON.stringify(fixture.match).slice(0, 120)}`);
@@ -528,7 +543,7 @@ async function handleOllama(req, res, raw, fixtures, journal, defaults, setCorsH
528
543
  body: completionReq
529
544
  }, fixture ? "fixture" : "proxy", defaults.registry, defaults.logger)) return;
530
545
  if (!fixture) {
531
- if (require_helpers.resolveStrictMode(defaults.strict, req.headers)) {
546
+ if (require_policy.resolveRequestDecisions(defaults.strict, req.headers).fixtureMiss) {
532
547
  const strictStatus = 503;
533
548
  const strictMessage = require_helpers.strictNoMatchMessage(skippedBySequenceOrTurn);
534
549
  logger.error(require_helpers.strictNoMatchLogLine(req.method ?? "POST", urlPath, skippedBySequenceOrTurn));
@@ -540,17 +555,17 @@ async function handleOllama(req, res, raw, fixtures, journal, defaults, setCorsH
540
555
  response: {
541
556
  status: strictStatus,
542
557
  fixture: null,
543
- ...require_helpers.strictOverrideField(defaults.strict, req.headers)
558
+ ...require_policy.strictOverrideField(defaults.strict, req.headers)
544
559
  }
545
560
  });
546
- require_sse_writer.writeErrorResponse(res, strictStatus, JSON.stringify({ error: {
561
+ require_sse_writer.writeErrorResponse(res, strictStatus, require_errors.renderError("ollama", "strict-miss", {
547
562
  message: strictMessage,
548
563
  type: "invalid_request_error"
549
- } }));
564
+ }).body);
550
565
  return;
551
566
  }
552
567
  if (defaults.record) {
553
- const outcome = await require_recorder.proxyAndRecord(req, res, completionReq, "ollama", urlPath, fixtures, defaults, raw);
568
+ const { outcome, clientHungUp } = await require_proxy.withHangUpDetection(req, res, () => require_recorder.proxyAndRecord(req, res, completionReq, "ollama", urlPath, fixtures, defaults, raw));
554
569
  if (outcome === "handled_by_hook") return;
555
570
  if (outcome !== "not_configured") {
556
571
  journal.add({
@@ -561,7 +576,8 @@ async function handleOllama(req, res, raw, fixtures, journal, defaults, setCorsH
561
576
  response: {
562
577
  status: res.statusCode ?? 200,
563
578
  fixture: null,
564
- source: "proxy"
579
+ source: "proxy",
580
+ ...require_proxy.proxyInterruption(res, clientHungUp)
565
581
  }
566
582
  });
567
583
  return;
@@ -575,13 +591,13 @@ async function handleOllama(req, res, raw, fixtures, journal, defaults, setCorsH
575
591
  response: {
576
592
  status: 404,
577
593
  fixture: null,
578
- ...require_helpers.strictOverrideField(defaults.strict, req.headers)
594
+ ...require_policy.strictOverrideField(defaults.strict, req.headers)
579
595
  }
580
596
  });
581
- require_sse_writer.writeErrorResponse(res, 404, JSON.stringify({ error: {
597
+ require_sse_writer.writeErrorResponse(res, 404, require_errors.renderError("ollama", "fixture-miss", {
582
598
  message: "No fixture matched",
583
599
  type: "invalid_request_error"
584
- } }));
600
+ }).body);
585
601
  return;
586
602
  }
587
603
  const response = await require_helpers.resolveResponse(fixture, completionReq);
@@ -613,14 +629,50 @@ async function handleOllama(req, res, raw, fixtures, journal, defaults, setCorsH
613
629
  });
614
630
  const message = `${misbehavior.code}: ${misbehavior.message}`;
615
631
  if (!misbehavior.summary?.evaluations.length) defaults.logger.error(message);
616
- require_sse_writer.writeErrorResponse(res, misbehavior.status, JSON.stringify({ error: message }));
632
+ require_sse_writer.writeErrorResponse(res, misbehavior.status, require_errors.renderError("ollama", "misbehavior", {
633
+ message: misbehavior.message,
634
+ code: misbehavior.code
635
+ }).body);
636
+ return;
637
+ }
638
+ if (require_helpers.isRawResponse(response)) {
639
+ await require_raw.serveRawResponse({
640
+ wire: "ollama",
641
+ stream: ollamaReq.stream !== false,
642
+ req,
643
+ res,
644
+ fixture,
645
+ response,
646
+ body: completionReq,
647
+ journal,
648
+ defaults,
649
+ testId,
650
+ misbehaviorSummary: misbehavior.summary,
651
+ errorWire: "ollama"
652
+ });
617
653
  return;
618
654
  }
619
655
  const latency = fixture.latency ?? defaults.latency;
620
656
  const chunkSize = Math.max(1, fixture.chunkSize ?? defaults.chunkSize);
657
+ const replaySpeed = fixture.replaySpeed ?? defaults.replaySpeed;
658
+ const streamTiming = {
659
+ latency,
660
+ streamingProfile: fixture.streamingProfile,
661
+ recordedTimings: fixture.recordedTimings,
662
+ replaySpeed
663
+ };
664
+ const jsonOpts = (payloadLength, duplicateId = false) => ({
665
+ surface: "other",
666
+ payloadLength,
667
+ chunkSize,
668
+ recordedTimings: fixture.recordedTimings,
669
+ duplicateId,
670
+ replaySpeed
671
+ });
621
672
  const streaming = ollamaReq.stream !== false;
622
673
  if (misbehavior.kind === "applied") {
623
- const prepared = prepareOllamaMisbehavior(misbehavior, completionReq, streaming, chunkSize, require_helpers.resolveStrictMode(defaults.strict, req.headers), logger);
674
+ const prepared = prepareOllamaMisbehavior(misbehavior, completionReq, streaming, chunkSize, require_policy.resolveRequestDecisions(defaults.strict, req.headers).reasoningSuppression, logger);
675
+ const chunks = !streaming && prepared.status === 200 && require_timing.nonStreamingTimingEnabled(fixture, "other") ? void 0 : prepared.build();
624
676
  const journalEntry = journal.add({
625
677
  method: req.method ?? "POST",
626
678
  path: urlPath,
@@ -637,24 +689,16 @@ async function handleOllama(req, res, raw, fixtures, journal, defaults, setCorsH
637
689
  defaults,
638
690
  testId
639
691
  });
640
- if (!streaming) {
692
+ if (!streaming && prepared.status !== 200) {
641
693
  res.writeHead(prepared.status, { "Content-Type": "application/json" });
642
- res.end(JSON.stringify(prepared.chunks[0]));
643
- } else {
644
- const interruption = require_interruption.createInterruptionSignal(fixture);
645
- if (!await require_ndjson_writer.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();
694
+ res.end(JSON.stringify((chunks ?? prepared.build())[0]));
695
+ } else if (!streaming) await require_deliver.deliverJson(res, journalEntry, fixture, () => (chunks ?? prepared.build())[0], {
696
+ ...jsonOpts(require_timing.misbehaviorPayloadLength(misbehavior, misbehavior.reasoning === void 0 ? prepared.reasoning : void 0), !!misbehavior.duplicateId),
697
+ status: prepared.status
698
+ });
699
+ else {
700
+ const frames = chunks ?? prepared.build();
701
+ await require_deliver.deliverStream(res, journalEntry, fixture, require_ndjson_writer.ndjsonCodec(), frames, streamTiming);
658
702
  }
659
703
  return;
660
704
  }
@@ -675,7 +719,7 @@ async function handleOllama(req, res, raw, fixtures, journal, defaults, setCorsH
675
719
  defaults,
676
720
  testId
677
721
  });
678
- require_sse_writer.writeErrorResponse(res, status, require_helpers.serializeErrorResponse(response), { retryAfter: response.retryAfter });
722
+ require_sse_writer.writeErrorResponse(res, status, require_errors.renderError("openai", "fixture", response.error).body, { retryAfter: response.retryAfter });
679
723
  return;
680
724
  }
681
725
  if (require_helpers.isCombinedFixtureResponse(response)) {
@@ -697,28 +741,12 @@ async function handleOllama(req, res, raw, fixtures, journal, defaults, setCorsH
697
741
  testId
698
742
  });
699
743
  const functionToolCalls = require_helpers.requireEmittedFunctionToolCalls(response, "Ollama");
700
- const effectiveStrict = require_helpers.resolveStrictMode(defaults.strict, req.headers);
744
+ const effectiveStrict = require_policy.resolveRequestDecisions(defaults.strict, req.headers).reasoningSuppression;
701
745
  const effReasoning = require_helpers.resolveReasoningForModel(response.reasoning, completionReq.model, effectiveStrict, logger);
702
- if (!streaming) {
703
- const body = buildOllamaChatContentWithToolCallsResponse(response.content ?? "", functionToolCalls, completionReq.model, effReasoning, response.blocks);
704
- res.writeHead(200, { "Content-Type": "application/json" });
705
- res.end(JSON.stringify(body));
706
- } else {
746
+ if (!streaming) await require_deliver.deliverJson(res, journalEntry, fixture, () => buildOllamaChatContentWithToolCallsResponse(response.content ?? "", functionToolCalls, completionReq.model, effReasoning, response.blocks), jsonOpts(require_timing.servedPayloadLength(response, effReasoning)));
747
+ else {
707
748
  const chunks = buildOllamaChatContentWithToolCallsChunks(response.content ?? "", functionToolCalls, completionReq.model, chunkSize, effReasoning, response.blocks);
708
- const interruption = require_interruption.createInterruptionSignal(fixture);
709
- if (!await require_ndjson_writer.writeNDJSONStream(res, chunks, {
710
- latency,
711
- streamingProfile: fixture.streamingProfile,
712
- recordedTimings: fixture.recordedTimings,
713
- replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed,
714
- signal: interruption?.signal,
715
- onChunkSent: interruption?.tick
716
- })) {
717
- if (!res.writableEnded) res.destroy();
718
- journalEntry.response.interrupted = true;
719
- journalEntry.response.interruptReason = interruption?.reason();
720
- }
721
- interruption?.cleanup();
749
+ await require_deliver.deliverStream(res, journalEntry, fixture, require_ndjson_writer.ndjsonCodec(), chunks, streamTiming);
722
750
  }
723
751
  return;
724
752
  }
@@ -740,28 +768,12 @@ async function handleOllama(req, res, raw, fixtures, journal, defaults, setCorsH
740
768
  defaults,
741
769
  testId
742
770
  });
743
- const effectiveStrict = require_helpers.resolveStrictMode(defaults.strict, req.headers);
771
+ const effectiveStrict = require_policy.resolveRequestDecisions(defaults.strict, req.headers).reasoningSuppression;
744
772
  const effReasoning = require_helpers.resolveReasoningForModel(response.reasoning, completionReq.model, effectiveStrict, logger);
745
- if (!streaming) {
746
- const body = buildOllamaChatTextResponse(response.content, completionReq.model, effReasoning);
747
- res.writeHead(200, { "Content-Type": "application/json" });
748
- res.end(JSON.stringify(body));
749
- } else {
773
+ if (!streaming) await require_deliver.deliverJson(res, journalEntry, fixture, () => buildOllamaChatTextResponse(response.content, completionReq.model, effReasoning), jsonOpts(require_timing.servedPayloadLength(response, effReasoning)));
774
+ else {
750
775
  const chunks = buildOllamaChatTextChunks(response.content, completionReq.model, chunkSize, effReasoning);
751
- const interruption = require_interruption.createInterruptionSignal(fixture);
752
- if (!await require_ndjson_writer.writeNDJSONStream(res, chunks, {
753
- latency,
754
- streamingProfile: fixture.streamingProfile,
755
- recordedTimings: fixture.recordedTimings,
756
- replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed,
757
- signal: interruption?.signal,
758
- onChunkSent: interruption?.tick
759
- })) {
760
- if (!res.writableEnded) res.destroy();
761
- journalEntry.response.interrupted = true;
762
- journalEntry.response.interruptReason = interruption?.reason();
763
- }
764
- interruption?.cleanup();
776
+ await require_deliver.deliverStream(res, journalEntry, fixture, require_ndjson_writer.ndjsonCodec(), chunks, streamTiming);
765
777
  }
766
778
  return;
767
779
  }
@@ -784,28 +796,12 @@ async function handleOllama(req, res, raw, fixtures, journal, defaults, setCorsH
784
796
  testId
785
797
  });
786
798
  const functionToolCalls = require_helpers.requireEmittedFunctionToolCalls(response, "Ollama");
787
- const effectiveStrict = require_helpers.resolveStrictMode(defaults.strict, req.headers);
799
+ const effectiveStrict = require_policy.resolveRequestDecisions(defaults.strict, req.headers).reasoningSuppression;
788
800
  const effReasoning = require_helpers.resolveReasoningForModel(response.reasoning, completionReq.model, effectiveStrict, logger);
789
- if (!streaming) {
790
- const body = buildOllamaChatToolCallResponse(functionToolCalls, completionReq.model, effReasoning);
791
- res.writeHead(200, { "Content-Type": "application/json" });
792
- res.end(JSON.stringify(body));
793
- } else {
801
+ if (!streaming) await require_deliver.deliverJson(res, journalEntry, fixture, () => buildOllamaChatToolCallResponse(functionToolCalls, completionReq.model, effReasoning), jsonOpts(require_timing.servedPayloadLength(response, effReasoning)));
802
+ else {
794
803
  const chunks = buildOllamaChatToolCallChunks(functionToolCalls, completionReq.model, chunkSize, effReasoning);
795
- const interruption = require_interruption.createInterruptionSignal(fixture);
796
- if (!await require_ndjson_writer.writeNDJSONStream(res, chunks, {
797
- latency,
798
- streamingProfile: fixture.streamingProfile,
799
- recordedTimings: fixture.recordedTimings,
800
- replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed,
801
- signal: interruption?.signal,
802
- onChunkSent: interruption?.tick
803
- })) {
804
- if (!res.writableEnded) res.destroy();
805
- journalEntry.response.interrupted = true;
806
- journalEntry.response.interruptReason = interruption?.reason();
807
- }
808
- interruption?.cleanup();
804
+ await require_deliver.deliverStream(res, journalEntry, fixture, require_ndjson_writer.ndjsonCodec(), chunks, streamTiming);
809
805
  }
810
806
  return;
811
807
  }
@@ -824,10 +820,10 @@ async function handleOllama(req, res, raw, fixtures, journal, defaults, setCorsH
824
820
  defaults,
825
821
  testId
826
822
  });
827
- require_sse_writer.writeErrorResponse(res, 500, JSON.stringify({ error: {
823
+ require_sse_writer.writeErrorResponse(res, 500, require_errors.renderError("ollama", "unknown-response", {
828
824
  message: "Fixture response did not match any known type",
829
825
  type: "server_error"
830
- } }));
826
+ }).body);
831
827
  }
832
828
  async function handleOllamaGenerate(req, res, raw, fixtures, journal, defaults, setCorsHeaders) {
833
829
  setCorsHeaders(res);
@@ -847,10 +843,10 @@ async function handleOllamaGenerate(req, res, raw, fixtures, journal, defaults,
847
843
  fixture: null
848
844
  }
849
845
  });
850
- require_sse_writer.writeErrorResponse(res, 400, JSON.stringify({ error: {
846
+ require_sse_writer.writeErrorResponse(res, 400, require_errors.renderError("ollama", "validation", {
851
847
  message: `Malformed JSON body: ${detail}`,
852
848
  type: "invalid_request_error"
853
- } }));
849
+ }).body);
854
850
  return;
855
851
  }
856
852
  if (!require_helpers.isJsonObject(generateReq)) {
@@ -864,10 +860,10 @@ async function handleOllamaGenerate(req, res, raw, fixtures, journal, defaults,
864
860
  fixture: null
865
861
  }
866
862
  });
867
- require_sse_writer.writeErrorResponse(res, 400, JSON.stringify({ error: {
863
+ require_sse_writer.writeErrorResponse(res, 400, require_errors.renderError("ollama", "validation", {
868
864
  message: "Request body must be a JSON object",
869
865
  type: "invalid_request_error"
870
- } }));
866
+ }).body);
871
867
  return;
872
868
  }
873
869
  if (!generateReq.prompt || typeof generateReq.prompt !== "string") {
@@ -881,17 +877,20 @@ async function handleOllamaGenerate(req, res, raw, fixtures, journal, defaults,
881
877
  fixture: null
882
878
  }
883
879
  });
884
- require_sse_writer.writeErrorResponse(res, 400, JSON.stringify({ error: {
880
+ require_sse_writer.writeErrorResponse(res, 400, require_errors.renderError("ollama", "validation", {
885
881
  message: "Invalid request: prompt field is required",
886
882
  type: "invalid_request_error"
887
- } }));
883
+ }).body);
888
884
  return;
889
885
  }
890
886
  const completionReq = ollamaGenerateToCompletionRequest(generateReq);
891
887
  completionReq._endpointType = "chat";
892
888
  completionReq._context = require_helpers.getContext(req);
893
889
  const testId = require_helpers.getTestId(req);
894
- const { fixture, skippedBySequenceOrTurn } = require_router.matchFixtureDiagnostic(fixtures, completionReq, journal.getFixtureMatchCountsForTest(testId), defaults.requestTransform, require_router.recordMatchOptions(!!defaults.record, defaults.logger));
890
+ const { fixture, skippedBySequenceOrTurn } = require_router.matchFixtureDiagnostic(fixtures, completionReq, journal.getFixtureMatchCountsForTest(testId), defaults.requestTransform, {
891
+ ...require_router.recordMatchOptions(!!defaults.record, defaults.logger),
892
+ wire: "ollama-generate"
893
+ });
895
894
  if (fixture) {
896
895
  journal.incrementFixtureMatchCount(fixture, fixtures, testId);
897
896
  defaults.logger.debug(`Fixture matched: ${JSON.stringify(fixture.match).slice(0, 120)}`);
@@ -903,7 +902,7 @@ async function handleOllamaGenerate(req, res, raw, fixtures, journal, defaults,
903
902
  body: completionReq
904
903
  }, fixture ? "fixture" : "proxy", defaults.registry, defaults.logger)) return;
905
904
  if (!fixture) {
906
- if (require_helpers.resolveStrictMode(defaults.strict, req.headers)) {
905
+ if (require_policy.resolveRequestDecisions(defaults.strict, req.headers).fixtureMiss) {
907
906
  const strictStatus = 503;
908
907
  const strictMessage = require_helpers.strictNoMatchMessage(skippedBySequenceOrTurn);
909
908
  defaults.logger.error(require_helpers.strictNoMatchLogLine(req.method ?? "POST", urlPath, skippedBySequenceOrTurn));
@@ -915,17 +914,17 @@ async function handleOllamaGenerate(req, res, raw, fixtures, journal, defaults,
915
914
  response: {
916
915
  status: strictStatus,
917
916
  fixture: null,
918
- ...require_helpers.strictOverrideField(defaults.strict, req.headers)
917
+ ...require_policy.strictOverrideField(defaults.strict, req.headers)
919
918
  }
920
919
  });
921
- require_sse_writer.writeErrorResponse(res, strictStatus, JSON.stringify({ error: {
920
+ require_sse_writer.writeErrorResponse(res, strictStatus, require_errors.renderError("ollama", "strict-miss", {
922
921
  message: strictMessage,
923
922
  type: "invalid_request_error"
924
- } }));
923
+ }).body);
925
924
  return;
926
925
  }
927
926
  if (defaults.record) {
928
- const outcome = await require_recorder.proxyAndRecord(req, res, completionReq, "ollama", urlPath, fixtures, defaults, raw);
927
+ const { outcome, clientHungUp } = await require_proxy.withHangUpDetection(req, res, () => require_recorder.proxyAndRecord(req, res, completionReq, "ollama", urlPath, fixtures, defaults, raw));
929
928
  if (outcome === "handled_by_hook") return;
930
929
  if (outcome !== "not_configured") {
931
930
  journal.add({
@@ -936,7 +935,8 @@ async function handleOllamaGenerate(req, res, raw, fixtures, journal, defaults,
936
935
  response: {
937
936
  status: res.statusCode ?? 200,
938
937
  fixture: null,
939
- source: "proxy"
938
+ source: "proxy",
939
+ ...require_proxy.proxyInterruption(res, clientHungUp)
940
940
  }
941
941
  });
942
942
  return;
@@ -950,13 +950,13 @@ async function handleOllamaGenerate(req, res, raw, fixtures, journal, defaults,
950
950
  response: {
951
951
  status: 404,
952
952
  fixture: null,
953
- ...require_helpers.strictOverrideField(defaults.strict, req.headers)
953
+ ...require_policy.strictOverrideField(defaults.strict, req.headers)
954
954
  }
955
955
  });
956
- require_sse_writer.writeErrorResponse(res, 404, JSON.stringify({ error: {
956
+ require_sse_writer.writeErrorResponse(res, 404, require_errors.renderError("ollama", "fixture-miss", {
957
957
  message: "No fixture matched",
958
958
  type: "invalid_request_error"
959
- } }));
959
+ }).body);
960
960
  return;
961
961
  }
962
962
  const response = await require_helpers.resolveResponse(fixture, completionReq);
@@ -989,11 +989,46 @@ async function handleOllamaGenerate(req, res, raw, fixtures, journal, defaults,
989
989
  });
990
990
  const message = `${misbehavior.code}: ${misbehavior.message}`;
991
991
  if (!misbehavior.summary?.evaluations.length) defaults.logger.error(message);
992
- require_sse_writer.writeErrorResponse(res, misbehavior.status, JSON.stringify({ error: message }));
992
+ require_sse_writer.writeErrorResponse(res, misbehavior.status, require_errors.renderError("ollama", "misbehavior", {
993
+ message: misbehavior.message,
994
+ code: misbehavior.code
995
+ }).body);
996
+ return;
997
+ }
998
+ if (require_helpers.isRawResponse(response)) {
999
+ await require_raw.serveRawResponse({
1000
+ wire: "ollama-generate",
1001
+ stream: generateReq.stream !== false,
1002
+ req,
1003
+ res,
1004
+ fixture,
1005
+ response,
1006
+ body: completionReq,
1007
+ journal,
1008
+ defaults,
1009
+ testId,
1010
+ misbehaviorSummary: misbehavior.summary,
1011
+ errorWire: "ollama"
1012
+ });
993
1013
  return;
994
1014
  }
995
1015
  const latency = fixture.latency ?? defaults.latency;
996
1016
  const chunkSize = Math.max(1, fixture.chunkSize ?? defaults.chunkSize);
1017
+ const replaySpeed = fixture.replaySpeed ?? defaults.replaySpeed;
1018
+ const streamTiming = {
1019
+ latency,
1020
+ streamingProfile: fixture.streamingProfile,
1021
+ recordedTimings: fixture.recordedTimings,
1022
+ replaySpeed
1023
+ };
1024
+ const jsonOpts = (payloadLength, duplicateId = false) => ({
1025
+ surface: "other",
1026
+ payloadLength,
1027
+ chunkSize,
1028
+ recordedTimings: fixture.recordedTimings,
1029
+ duplicateId,
1030
+ replaySpeed
1031
+ });
997
1032
  const streaming = generateReq.stream !== false;
998
1033
  if (require_helpers.isErrorResponse(response)) {
999
1034
  const status = response.status ?? 500;
@@ -1012,7 +1047,7 @@ async function handleOllamaGenerate(req, res, raw, fixtures, journal, defaults,
1012
1047
  defaults,
1013
1048
  testId
1014
1049
  });
1015
- require_sse_writer.writeErrorResponse(res, status, require_helpers.serializeErrorResponse(response), { retryAfter: response.retryAfter });
1050
+ require_sse_writer.writeErrorResponse(res, status, require_errors.renderError("openai", "fixture", response.error).body, { retryAfter: response.retryAfter });
1016
1051
  return;
1017
1052
  }
1018
1053
  if (require_helpers.isTextResponse(response)) {
@@ -1032,28 +1067,12 @@ async function handleOllamaGenerate(req, res, raw, fixtures, journal, defaults,
1032
1067
  defaults,
1033
1068
  testId
1034
1069
  });
1035
- const effectiveStrict = require_helpers.resolveStrictMode(defaults.strict, req.headers);
1070
+ const effectiveStrict = require_policy.resolveRequestDecisions(defaults.strict, req.headers).reasoningSuppression;
1036
1071
  const effReasoning = require_helpers.resolveReasoningForModel(response.reasoning, completionReq.model, effectiveStrict, defaults.logger);
1037
- if (!streaming) {
1038
- const body = buildOllamaGenerateTextResponse(response.content, completionReq.model, effReasoning);
1039
- res.writeHead(200, { "Content-Type": "application/json" });
1040
- res.end(JSON.stringify(body));
1041
- } else {
1072
+ if (!streaming) await require_deliver.deliverJson(res, journalEntry, fixture, () => buildOllamaGenerateTextResponse(response.content, completionReq.model, effReasoning), jsonOpts(require_timing.servedPayloadLength({ content: response.content }, effReasoning)));
1073
+ else {
1042
1074
  const chunks = buildOllamaGenerateTextChunks(response.content, completionReq.model, chunkSize, effReasoning);
1043
- const interruption = require_interruption.createInterruptionSignal(fixture);
1044
- if (!await require_ndjson_writer.writeNDJSONStream(res, chunks, {
1045
- latency,
1046
- streamingProfile: fixture.streamingProfile,
1047
- recordedTimings: fixture.recordedTimings,
1048
- replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed,
1049
- signal: interruption?.signal,
1050
- onChunkSent: interruption?.tick
1051
- })) {
1052
- if (!res.writableEnded) res.destroy();
1053
- journalEntry.response.interrupted = true;
1054
- journalEntry.response.interruptReason = interruption?.reason();
1055
- }
1056
- interruption?.cleanup();
1075
+ await require_deliver.deliverStream(res, journalEntry, fixture, require_ndjson_writer.ndjsonCodec(), chunks, streamTiming);
1057
1076
  }
1058
1077
  return;
1059
1078
  }
@@ -1073,10 +1092,10 @@ async function handleOllamaGenerate(req, res, raw, fixtures, journal, defaults,
1073
1092
  defaults,
1074
1093
  testId
1075
1094
  });
1076
- require_sse_writer.writeErrorResponse(res, 400, JSON.stringify({ error: {
1095
+ require_sse_writer.writeErrorResponse(res, 400, require_errors.renderError("ollama", "validation", {
1077
1096
  message: "Tool call fixtures are not supported on /api/generate — use /api/chat instead",
1078
1097
  type: "invalid_request_error"
1079
- } }));
1098
+ }).body);
1080
1099
  return;
1081
1100
  }
1082
1101
  require_misbehavior.recordMisbehaviorOutcome({
@@ -1094,15 +1113,17 @@ async function handleOllamaGenerate(req, res, raw, fixtures, journal, defaults,
1094
1113
  defaults,
1095
1114
  testId
1096
1115
  });
1097
- require_sse_writer.writeErrorResponse(res, 500, JSON.stringify({ error: {
1116
+ require_sse_writer.writeErrorResponse(res, 500, require_errors.renderError("ollama", "unknown-response", {
1098
1117
  message: "Fixture response did not match any known type",
1099
1118
  type: "server_error"
1100
- } }));
1119
+ }).body);
1101
1120
  }
1102
1121
  async function handleOllamaEmbeddings(req, res, raw, fixtures, journal, defaults, setCorsHeaders) {
1103
1122
  const { logger } = defaults;
1104
1123
  setCorsHeaders(res);
1105
1124
  const urlPath = req.url ?? "/api/embeddings";
1125
+ const currentEndpoint = urlPath.split("?")[0] === "/api/embed";
1126
+ const errorWire = currentEndpoint ? "ollama-embed" : "ollama";
1106
1127
  let embReq;
1107
1128
  try {
1108
1129
  embReq = JSON.parse(raw);
@@ -1118,10 +1139,10 @@ async function handleOllamaEmbeddings(req, res, raw, fixtures, journal, defaults
1118
1139
  fixture: null
1119
1140
  }
1120
1141
  });
1121
- require_sse_writer.writeErrorResponse(res, 400, JSON.stringify({ error: {
1142
+ require_sse_writer.writeErrorResponse(res, 400, require_errors.renderError(errorWire, "validation", {
1122
1143
  message: `Malformed JSON body: ${detail}`,
1123
1144
  type: "invalid_request_error"
1124
- } }));
1145
+ }).body);
1125
1146
  return;
1126
1147
  }
1127
1148
  if (!require_helpers.isJsonObject(embReq)) {
@@ -1135,10 +1156,10 @@ async function handleOllamaEmbeddings(req, res, raw, fixtures, journal, defaults
1135
1156
  fixture: null
1136
1157
  }
1137
1158
  });
1138
- require_sse_writer.writeErrorResponse(res, 400, JSON.stringify({ error: {
1159
+ require_sse_writer.writeErrorResponse(res, 400, require_errors.renderError(errorWire, "validation", {
1139
1160
  message: "Request body must be a JSON object",
1140
1161
  type: "invalid_request_error"
1141
- } }));
1162
+ }).body);
1142
1163
  return;
1143
1164
  }
1144
1165
  const promptShapeError = embReq.prompt !== void 0 && embReq.prompt !== null && typeof embReq.prompt !== "string" ? "prompt field must be a string" : embReq.input !== void 0 && embReq.input !== null && require_helpers.normalizeEmbeddingInput(embReq.input) === null ? "input field must be a string or an array of strings" : null;
@@ -1153,14 +1174,15 @@ async function handleOllamaEmbeddings(req, res, raw, fixtures, journal, defaults
1153
1174
  fixture: null
1154
1175
  }
1155
1176
  });
1156
- require_sse_writer.writeErrorResponse(res, 400, JSON.stringify({ error: {
1177
+ require_sse_writer.writeErrorResponse(res, 400, require_errors.renderError(errorWire, "validation", {
1157
1178
  message: `Invalid request: ${promptShapeError}`,
1158
1179
  type: "invalid_request_error"
1159
- } }));
1180
+ }).body);
1160
1181
  return;
1161
1182
  }
1162
- const inputText = embReq.prompt ?? (typeof embReq.input === "string" ? embReq.input : void 0) ?? (Array.isArray(embReq.input) ? embReq.input.join(" ") : void 0);
1163
- if (!embReq.model) {
1183
+ const inputs = require_helpers.normalizeEmbeddingInput(currentEndpoint ? embReq.input ?? embReq.prompt : embReq.prompt ?? embReq.input);
1184
+ const inputText = currentEndpoint ? inputs?.join(" ") : embReq.prompt ?? (typeof embReq.input === "string" ? embReq.input : void 0) ?? (Array.isArray(embReq.input) ? embReq.input.join(" ") : void 0);
1185
+ if (!embReq.model || currentEndpoint && typeof embReq.model !== "string") {
1164
1186
  journal.add({
1165
1187
  method: req.method ?? "POST",
1166
1188
  path: urlPath,
@@ -1171,10 +1193,10 @@ async function handleOllamaEmbeddings(req, res, raw, fixtures, journal, defaults
1171
1193
  fixture: null
1172
1194
  }
1173
1195
  });
1174
- require_sse_writer.writeErrorResponse(res, 400, JSON.stringify({ error: {
1196
+ require_sse_writer.writeErrorResponse(res, 400, require_errors.renderError(errorWire, "validation", {
1175
1197
  message: "Invalid request: model field is required",
1176
1198
  type: "invalid_request_error"
1177
- } }));
1199
+ }).body);
1178
1200
  return;
1179
1201
  }
1180
1202
  if (!inputText) {
@@ -1188,10 +1210,10 @@ async function handleOllamaEmbeddings(req, res, raw, fixtures, journal, defaults
1188
1210
  fixture: null
1189
1211
  }
1190
1212
  });
1191
- require_sse_writer.writeErrorResponse(res, 400, JSON.stringify({ error: {
1213
+ require_sse_writer.writeErrorResponse(res, 400, require_errors.renderError(errorWire, "validation", {
1192
1214
  message: "Invalid request: prompt or input field is required",
1193
1215
  type: "invalid_request_error"
1194
- } }));
1216
+ }).body);
1195
1217
  return;
1196
1218
  }
1197
1219
  const syntheticReq = {
@@ -1201,6 +1223,11 @@ async function handleOllamaEmbeddings(req, res, raw, fixtures, journal, defaults
1201
1223
  _endpointType: "embedding",
1202
1224
  _context: require_helpers.getContext(req)
1203
1225
  };
1226
+ require_embedding_request.setEmbeddingRequest(syntheticReq, {
1227
+ operation: currentEndpoint ? "/api/embed" : "/api/embeddings",
1228
+ input: currentEndpoint ? embReq.input ?? embReq.prompt ?? "" : embReq.prompt ?? embReq.input ?? "",
1229
+ ...embReq.dimensions !== void 0 && { dimensions: embReq.dimensions }
1230
+ });
1204
1231
  const testId = require_helpers.getTestId(req);
1205
1232
  const { fixture, skippedBySequenceOrTurn } = require_router.matchFixtureDiagnostic(fixtures, syntheticReq, journal.getFixtureMatchCountsForTest(testId), defaults.requestTransform, require_router.recordMatchOptions(!!defaults.record, defaults.logger));
1206
1233
  if (fixture) {
@@ -1227,7 +1254,23 @@ async function handleOllamaEmbeddings(req, res, raw, fixtures, journal, defaults
1227
1254
  fixture
1228
1255
  }
1229
1256
  });
1230
- require_sse_writer.writeErrorResponse(res, status, require_helpers.serializeErrorResponse(response), { retryAfter: response.retryAfter });
1257
+ require_sse_writer.writeErrorResponse(res, status, require_errors.renderError(currentEndpoint ? "ollama-embed" : "openai", "fixture", response.error).body, { retryAfter: response.retryAfter });
1258
+ return;
1259
+ }
1260
+ if (currentEndpoint && require_helpers.isJSONResponse(response)) {
1261
+ const status = response.status ?? 200;
1262
+ journal.add({
1263
+ method: req.method ?? "POST",
1264
+ path: urlPath,
1265
+ headers: require_helpers.flattenHeaders(req.headers),
1266
+ body: syntheticReq,
1267
+ response: {
1268
+ status,
1269
+ fixture
1270
+ }
1271
+ });
1272
+ res.writeHead(status, { "Content-Type": "application/json" });
1273
+ res.end(JSON.stringify(response.json));
1231
1274
  return;
1232
1275
  }
1233
1276
  if (require_helpers.isEmbeddingResponse(response)) {
@@ -1241,7 +1284,10 @@ async function handleOllamaEmbeddings(req, res, raw, fixtures, journal, defaults
1241
1284
  fixture
1242
1285
  }
1243
1286
  });
1244
- const body = {
1287
+ const body = currentEndpoint ? {
1288
+ model: embReq.model,
1289
+ embeddings: (inputs ?? []).map(() => [...response.embedding])
1290
+ } : {
1245
1291
  model: embReq.model,
1246
1292
  embedding: [...response.embedding]
1247
1293
  };
@@ -1259,13 +1305,13 @@ async function handleOllamaEmbeddings(req, res, raw, fixtures, journal, defaults
1259
1305
  fixture
1260
1306
  }
1261
1307
  });
1262
- require_sse_writer.writeErrorResponse(res, 500, JSON.stringify({ error: {
1308
+ require_sse_writer.writeErrorResponse(res, 500, require_errors.renderError(errorWire, "unknown-response", {
1263
1309
  message: "Fixture response did not match any known embedding type (must have embedding or error)",
1264
1310
  type: "server_error"
1265
- } }));
1311
+ }).body);
1266
1312
  return;
1267
1313
  }
1268
- if (require_helpers.resolveStrictMode(defaults.strict, req.headers)) {
1314
+ if (require_policy.resolveRequestDecisions(defaults.strict, req.headers).fixtureMiss) {
1269
1315
  const strictMessage = require_helpers.strictNoMatchMessage(skippedBySequenceOrTurn);
1270
1316
  logger.error(require_helpers.strictNoMatchLogLine(req.method ?? "POST", urlPath, skippedBySequenceOrTurn));
1271
1317
  journal.add({
@@ -1276,13 +1322,13 @@ async function handleOllamaEmbeddings(req, res, raw, fixtures, journal, defaults
1276
1322
  response: {
1277
1323
  status: 503,
1278
1324
  fixture: null,
1279
- ...require_helpers.strictOverrideField(defaults.strict, req.headers)
1325
+ ...require_policy.strictOverrideField(defaults.strict, req.headers)
1280
1326
  }
1281
1327
  });
1282
- require_sse_writer.writeErrorResponse(res, 503, JSON.stringify({ error: {
1328
+ require_sse_writer.writeErrorResponse(res, 503, require_errors.renderError(errorWire, "strict-miss", {
1283
1329
  message: strictMessage,
1284
1330
  type: "invalid_request_error"
1285
- } }));
1331
+ }).body);
1286
1332
  return;
1287
1333
  }
1288
1334
  if (defaults.record) {
@@ -1303,8 +1349,25 @@ async function handleOllamaEmbeddings(req, res, raw, fixtures, journal, defaults
1303
1349
  return;
1304
1350
  }
1305
1351
  }
1352
+ const dimensions = currentEndpoint ? require_helpers.validateEmbeddingDimensions(embReq.dimensions) : 1536;
1353
+ if (dimensions === null) {
1354
+ journal.add({
1355
+ method: req.method ?? "POST",
1356
+ path: urlPath,
1357
+ headers: require_helpers.flattenHeaders(req.headers),
1358
+ body: syntheticReq,
1359
+ response: {
1360
+ status: 400,
1361
+ fixture: null
1362
+ }
1363
+ });
1364
+ require_sse_writer.writeErrorResponse(res, 400, require_errors.renderError(errorWire, "validation", {
1365
+ message: `Invalid request: dimensions must be an integer between 1 and ${require_helpers.MAX_EMBEDDING_DIMENSIONS}`,
1366
+ type: "invalid_request_error"
1367
+ }).body);
1368
+ return;
1369
+ }
1306
1370
  logger.warn(`No embedding fixture matched for "${inputText.slice(0, 80)}" — returning deterministic fallback`);
1307
- const embedding = require_helpers.generateDeterministicEmbedding(inputText);
1308
1371
  journal.add({
1309
1372
  method: req.method ?? "POST",
1310
1373
  path: urlPath,
@@ -1315,9 +1378,12 @@ async function handleOllamaEmbeddings(req, res, raw, fixtures, journal, defaults
1315
1378
  fixture: null
1316
1379
  }
1317
1380
  });
1318
- const body = {
1381
+ const body = currentEndpoint ? {
1382
+ model: embReq.model,
1383
+ embeddings: (inputs ?? []).map((input) => require_helpers.generateDeterministicEmbedding(input, dimensions))
1384
+ } : {
1319
1385
  model: embReq.model,
1320
- embedding
1386
+ embedding: require_helpers.generateDeterministicEmbedding(inputText)
1321
1387
  };
1322
1388
  res.writeHead(200, { "Content-Type": "application/json" });
1323
1389
  res.end(JSON.stringify(body));