@copilotkit/aimock 1.44.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 (272) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +31 -0
  4. package/README.md +6 -0
  5. package/dist/agui-types.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 +312 -39
  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 +313 -40
  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 +1 -0
  25. package/dist/chaos.js +1 -1
  26. package/dist/cli.cjs +152 -5
  27. package/dist/cli.cjs.map +1 -1
  28. package/dist/cli.js +155 -8
  29. package/dist/cli.js.map +1 -1
  30. package/dist/cohere.cjs +132 -71
  31. package/dist/cohere.cjs.map +1 -1
  32. package/dist/cohere.d.cts.map +1 -1
  33. package/dist/cohere.d.ts.map +1 -1
  34. package/dist/cohere.js +133 -72
  35. package/dist/cohere.js.map +1 -1
  36. package/dist/config-loader.cjs +62 -4
  37. package/dist/config-loader.cjs.map +1 -1
  38. package/dist/config-loader.d.cts +37 -4
  39. package/dist/config-loader.d.cts.map +1 -1
  40. package/dist/config-loader.d.ts +37 -4
  41. package/dist/config-loader.d.ts.map +1 -1
  42. package/dist/config-loader.js +62 -4
  43. package/dist/config-loader.js.map +1 -1
  44. package/dist/fakes-plugin.cjs +131 -0
  45. package/dist/fakes-plugin.cjs.map +1 -0
  46. package/dist/fakes-plugin.d.cts +23 -0
  47. package/dist/fakes-plugin.d.cts.map +1 -0
  48. package/dist/fakes-plugin.d.ts +23 -0
  49. package/dist/fakes-plugin.d.ts.map +1 -0
  50. package/dist/fakes-plugin.js +127 -0
  51. package/dist/fakes-plugin.js.map +1 -0
  52. package/dist/fixture-loader-services.cjs +1 -1
  53. package/dist/fixture-loader-services.cjs.map +1 -1
  54. package/dist/fixture-loader-services.js +1 -1
  55. package/dist/fixture-loader-services.js.map +1 -1
  56. package/dist/fixture-loader.cjs +389 -27
  57. package/dist/fixture-loader.cjs.map +1 -1
  58. package/dist/fixture-loader.d.cts +47 -3
  59. package/dist/fixture-loader.d.cts.map +1 -1
  60. package/dist/fixture-loader.d.ts +47 -3
  61. package/dist/fixture-loader.d.ts.map +1 -1
  62. package/dist/fixture-loader.js +384 -29
  63. package/dist/fixture-loader.js.map +1 -1
  64. package/dist/gemini-interactions.cjs +250 -52
  65. package/dist/gemini-interactions.cjs.map +1 -1
  66. package/dist/gemini-interactions.d.cts.map +1 -1
  67. package/dist/gemini-interactions.d.ts.map +1 -1
  68. package/dist/gemini-interactions.js +251 -53
  69. package/dist/gemini-interactions.js.map +1 -1
  70. package/dist/gemini.cjs +226 -37
  71. package/dist/gemini.cjs.map +1 -1
  72. package/dist/gemini.d.cts.map +1 -1
  73. package/dist/gemini.d.ts.map +1 -1
  74. package/dist/gemini.js +227 -38
  75. package/dist/gemini.js.map +1 -1
  76. package/dist/helpers.cjs +881 -7
  77. package/dist/helpers.cjs.map +1 -1
  78. package/dist/helpers.d.cts +85 -4
  79. package/dist/helpers.d.cts.map +1 -1
  80. package/dist/helpers.d.ts +85 -4
  81. package/dist/helpers.d.ts.map +1 -1
  82. package/dist/helpers.js +839 -8
  83. package/dist/helpers.js.map +1 -1
  84. package/dist/index.cjs +9 -0
  85. package/dist/index.d.cts +7 -5
  86. package/dist/index.d.ts +7 -5
  87. package/dist/index.js +4 -3
  88. package/dist/jest.cjs +31 -7
  89. package/dist/jest.cjs.map +1 -1
  90. package/dist/jest.d.cts +43 -3
  91. package/dist/jest.d.cts.map +1 -1
  92. package/dist/jest.d.ts +43 -3
  93. package/dist/jest.d.ts.map +1 -1
  94. package/dist/jest.js +33 -9
  95. package/dist/jest.js.map +1 -1
  96. package/dist/journal.cjs +135 -13
  97. package/dist/journal.cjs.map +1 -1
  98. package/dist/journal.d.cts +38 -4
  99. package/dist/journal.d.cts.map +1 -1
  100. package/dist/journal.d.ts +38 -4
  101. package/dist/journal.d.ts.map +1 -1
  102. package/dist/journal.js +135 -13
  103. package/dist/journal.js.map +1 -1
  104. package/dist/live-sanitize.cjs +4 -32
  105. package/dist/live-sanitize.cjs.map +1 -1
  106. package/dist/live-sanitize.js +4 -32
  107. package/dist/live-sanitize.js.map +1 -1
  108. package/dist/llmock.cjs +123 -30
  109. package/dist/llmock.cjs.map +1 -1
  110. package/dist/llmock.d.cts +16 -1
  111. package/dist/llmock.d.cts.map +1 -1
  112. package/dist/llmock.d.ts +16 -1
  113. package/dist/llmock.d.ts.map +1 -1
  114. package/dist/llmock.js +125 -32
  115. package/dist/llmock.js.map +1 -1
  116. package/dist/mcp-fakes-mount.cjs +1 -0
  117. package/dist/mcp-fakes-mount.cjs.map +1 -1
  118. package/dist/mcp-fakes-mount.js +1 -0
  119. package/dist/mcp-fakes-mount.js.map +1 -1
  120. package/dist/mcp-fakes-report.cjs +111 -0
  121. package/dist/mcp-fakes-report.cjs.map +1 -0
  122. package/dist/mcp-fakes-report.d.cts +40 -0
  123. package/dist/mcp-fakes-report.d.cts.map +1 -0
  124. package/dist/mcp-fakes-report.d.ts +40 -0
  125. package/dist/mcp-fakes-report.d.ts.map +1 -0
  126. package/dist/mcp-fakes-report.js +107 -0
  127. package/dist/mcp-fakes-report.js.map +1 -0
  128. package/dist/mcp-fakes.cjs +331 -8
  129. package/dist/mcp-fakes.cjs.map +1 -1
  130. package/dist/mcp-fakes.d.cts +406 -3
  131. package/dist/mcp-fakes.d.cts.map +1 -1
  132. package/dist/mcp-fakes.d.ts +406 -3
  133. package/dist/mcp-fakes.d.ts.map +1 -1
  134. package/dist/mcp-fakes.js +331 -8
  135. package/dist/mcp-fakes.js.map +1 -1
  136. package/dist/mcp-handler.cjs +209 -16
  137. package/dist/mcp-handler.cjs.map +1 -1
  138. package/dist/mcp-handler.d.cts +49 -0
  139. package/dist/mcp-handler.d.cts.map +1 -0
  140. package/dist/mcp-handler.d.ts +49 -0
  141. package/dist/mcp-handler.d.ts.map +1 -0
  142. package/dist/mcp-handler.js +207 -17
  143. package/dist/mcp-handler.js.map +1 -1
  144. package/dist/mcp-mock.cjs +112 -1
  145. package/dist/mcp-mock.cjs.map +1 -1
  146. package/dist/mcp-mock.d.cts +33 -2
  147. package/dist/mcp-mock.d.cts.map +1 -1
  148. package/dist/mcp-mock.d.ts +33 -2
  149. package/dist/mcp-mock.d.ts.map +1 -1
  150. package/dist/mcp-mock.js +112 -1
  151. package/dist/mcp-mock.js.map +1 -1
  152. package/dist/mcp-recorder.cjs +1224 -0
  153. package/dist/mcp-recorder.cjs.map +1 -0
  154. package/dist/mcp-recorder.d.cts +108 -0
  155. package/dist/mcp-recorder.d.cts.map +1 -0
  156. package/dist/mcp-recorder.d.ts +108 -0
  157. package/dist/mcp-recorder.d.ts.map +1 -0
  158. package/dist/mcp-recorder.js +1215 -0
  159. package/dist/mcp-recorder.js.map +1 -0
  160. package/dist/messages.cjs +362 -56
  161. package/dist/messages.cjs.map +1 -1
  162. package/dist/messages.d.cts.map +1 -1
  163. package/dist/messages.d.ts.map +1 -1
  164. package/dist/messages.js +363 -58
  165. package/dist/messages.js.map +1 -1
  166. package/dist/misbehavior.cjs +1523 -0
  167. package/dist/misbehavior.cjs.map +1 -0
  168. package/dist/misbehavior.d.cts +43 -0
  169. package/dist/misbehavior.d.cts.map +1 -0
  170. package/dist/misbehavior.d.ts +43 -0
  171. package/dist/misbehavior.d.ts.map +1 -0
  172. package/dist/misbehavior.js +1511 -0
  173. package/dist/misbehavior.js.map +1 -0
  174. package/dist/ollama.cjs +310 -112
  175. package/dist/ollama.cjs.map +1 -1
  176. package/dist/ollama.d.cts.map +1 -1
  177. package/dist/ollama.d.ts.map +1 -1
  178. package/dist/ollama.js +311 -113
  179. package/dist/ollama.js.map +1 -1
  180. package/dist/record-sanitize.cjs +231 -0
  181. package/dist/record-sanitize.cjs.map +1 -0
  182. package/dist/record-sanitize.js +224 -0
  183. package/dist/record-sanitize.js.map +1 -0
  184. package/dist/recorder.cjs +106 -5
  185. package/dist/recorder.cjs.map +1 -1
  186. package/dist/recorder.d.cts +2 -1
  187. package/dist/recorder.d.cts.map +1 -1
  188. package/dist/recorder.d.ts +2 -1
  189. package/dist/recorder.d.ts.map +1 -1
  190. package/dist/recorder.js +107 -7
  191. package/dist/recorder.js.map +1 -1
  192. package/dist/responses.cjs +667 -171
  193. package/dist/responses.cjs.map +1 -1
  194. package/dist/responses.d.cts +5 -13
  195. package/dist/responses.d.cts.map +1 -1
  196. package/dist/responses.d.ts +5 -13
  197. package/dist/responses.d.ts.map +1 -1
  198. package/dist/responses.js +665 -174
  199. package/dist/responses.js.map +1 -1
  200. package/dist/router.cjs +24 -2
  201. package/dist/router.cjs.map +1 -1
  202. package/dist/router.d.cts.map +1 -1
  203. package/dist/router.d.ts.map +1 -1
  204. package/dist/router.js +25 -4
  205. package/dist/router.js.map +1 -1
  206. package/dist/server.cjs +572 -76
  207. package/dist/server.cjs.map +1 -1
  208. package/dist/server.d.cts.map +1 -1
  209. package/dist/server.d.ts.map +1 -1
  210. package/dist/server.js +574 -78
  211. package/dist/server.js.map +1 -1
  212. package/dist/stream-collapse.cjs +236 -34
  213. package/dist/stream-collapse.cjs.map +1 -1
  214. package/dist/stream-collapse.d.cts +39 -4
  215. package/dist/stream-collapse.d.cts.map +1 -1
  216. package/dist/stream-collapse.d.ts +39 -4
  217. package/dist/stream-collapse.d.ts.map +1 -1
  218. package/dist/stream-collapse.js +235 -35
  219. package/dist/stream-collapse.js.map +1 -1
  220. package/dist/types.cjs.map +1 -1
  221. package/dist/types.d.cts +315 -4
  222. package/dist/types.d.cts.map +1 -1
  223. package/dist/types.d.ts +315 -4
  224. package/dist/types.d.ts.map +1 -1
  225. package/dist/types.js.map +1 -1
  226. package/dist/validate-cli.cjs +36 -4
  227. package/dist/validate-cli.cjs.map +1 -1
  228. package/dist/validate-cli.js +37 -5
  229. package/dist/validate-cli.js.map +1 -1
  230. package/dist/vector-types.d.ts.map +1 -1
  231. package/dist/version.cjs +45 -0
  232. package/dist/version.cjs.map +1 -0
  233. package/dist/version.js +44 -0
  234. package/dist/version.js.map +1 -0
  235. package/dist/vitest.cjs +66 -10
  236. package/dist/vitest.cjs.map +1 -1
  237. package/dist/vitest.d.cts +35 -4
  238. package/dist/vitest.d.cts.map +1 -1
  239. package/dist/vitest.d.ts +35 -4
  240. package/dist/vitest.d.ts.map +1 -1
  241. package/dist/vitest.js +67 -11
  242. package/dist/vitest.js.map +1 -1
  243. package/dist/watcher.cjs +6 -2
  244. package/dist/watcher.cjs.map +1 -1
  245. package/dist/watcher.js +6 -2
  246. package/dist/watcher.js.map +1 -1
  247. package/dist/ws-gemini-live.cjs +210 -101
  248. package/dist/ws-gemini-live.cjs.map +1 -1
  249. package/dist/ws-gemini-live.d.cts +9 -3
  250. package/dist/ws-gemini-live.d.cts.map +1 -1
  251. package/dist/ws-gemini-live.d.ts +9 -3
  252. package/dist/ws-gemini-live.d.ts.map +1 -1
  253. package/dist/ws-gemini-live.js +211 -102
  254. package/dist/ws-gemini-live.js.map +1 -1
  255. package/dist/ws-realtime.cjs +175 -62
  256. package/dist/ws-realtime.cjs.map +1 -1
  257. package/dist/ws-realtime.d.cts +8 -3
  258. package/dist/ws-realtime.d.cts.map +1 -1
  259. package/dist/ws-realtime.d.ts +8 -3
  260. package/dist/ws-realtime.d.ts.map +1 -1
  261. package/dist/ws-realtime.js +176 -63
  262. package/dist/ws-realtime.js.map +1 -1
  263. package/dist/ws-responses.cjs +109 -16
  264. package/dist/ws-responses.cjs.map +1 -1
  265. package/dist/ws-responses.d.cts +8 -12
  266. package/dist/ws-responses.d.cts.map +1 -1
  267. package/dist/ws-responses.d.ts +8 -12
  268. package/dist/ws-responses.d.ts.map +1 -1
  269. package/dist/ws-responses.js +111 -18
  270. package/dist/ws-responses.js.map +1 -1
  271. package/package.json +10 -2
  272. package/skills/write-fixtures/SKILL.md +179 -21
package/dist/server.cjs CHANGED
@@ -6,6 +6,7 @@ const require_helpers = require('./helpers.cjs');
6
6
  const require_live_fixture = require('./live-fixture.cjs');
7
7
  const require_sse_writer = require('./sse-writer.cjs');
8
8
  const require_chaos = require('./chaos.cjs');
9
+ const require_misbehavior = require('./misbehavior.cjs');
9
10
  const require_fixture_loader = require('./fixture-loader.cjs');
10
11
  const require_router = require('./router.cjs');
11
12
  const require_recorder = require('./recorder.cjs');
@@ -53,6 +54,7 @@ const require_metrics = require('./metrics.cjs');
53
54
  const require_mcp_fakes = require('./mcp-fakes.cjs');
54
55
  const require_mcp_mock = require('./mcp-mock.cjs');
55
56
  const require_mcp_fakes_mount = require('./mcp-fakes-mount.cjs');
57
+ const require_mcp_fakes_report = require('./mcp-fakes-report.cjs');
56
58
  let node_http = require("node:http");
57
59
  node_http = require_runtime.__toESM(node_http);
58
60
  let node_async_hooks = require("node:async_hooks");
@@ -161,6 +163,7 @@ function performFullReset(fixtures, targets) {
161
163
  targets.journal.clear();
162
164
  require_chaos.resetChaosWarnings(targets.defaults.logger);
163
165
  targets.defaults.chaos = void 0;
166
+ targets.defaults.misbehavior?.byTestId.clear();
164
167
  targets.videoStates.clear();
165
168
  targets.openRouterVideoJobs.clear();
166
169
  targets.veoVideoJobs.clear();
@@ -206,7 +209,7 @@ function fixtureResponseKind(response) {
206
209
  if (require_helpers.isImageResponse(response)) return "image";
207
210
  if (require_helpers.isEmbeddingResponse(response)) return "embedding";
208
211
  if (require_helpers.isJSONResponse(response)) return "json";
209
- if (require_helpers.isContentWithToolCallsResponse(response)) return "contentWithToolCalls";
212
+ if (require_helpers.isCombinedFixtureResponse(response)) return "contentWithToolCalls";
210
213
  if (require_helpers.isToolCallResponse(response)) return "toolCalls";
211
214
  if (require_helpers.isTextResponse(response)) return "text";
212
215
  return "unknown";
@@ -370,7 +373,8 @@ function planControlApiFakes(raw, mounts) {
370
373
  const target = require_mcp_fakes_mount.ensureFakeMount(mounts, group.path, {
371
374
  journal: wiring.journal,
372
375
  registry: wiring.defaults.registry,
373
- logger: wiring.defaults.logger
376
+ logger: wiring.defaults.logger,
377
+ replaySpeed: wiring.defaults.replaySpeed
374
378
  }, wiring.defaults.logger);
375
379
  if ("conflict" in target) continue;
376
380
  const result = target.handler.addMcpFakes?.(group.sources, { kind: "control-api" });
@@ -421,6 +425,7 @@ function listControlApiFakes(mounts, testId, context, mount) {
421
425
  }] : []);
422
426
  return mount !== null && listed.length === 0 ? null : listed;
423
427
  }
428
+ const controlFixtureAdditions = /* @__PURE__ */ new WeakMap();
424
429
  /**
425
430
  * Handle requests under `/__aimock/`. Returns `true` if the request was
426
431
  * handled, `false` if the path doesn't match the control prefix.
@@ -492,7 +497,7 @@ async function handleControlAPI(req, res, pathname, searchParams, fixtures, jour
492
497
  "Content-Type": "application/json",
493
498
  "X-Total-Count": String(total)
494
499
  });
495
- res.end(JSON.stringify(entries));
500
+ res.end(journalJson(entries, journal));
496
501
  return true;
497
502
  }
498
503
  if (subPath === "/fixtures" && req.method === "GET") {
@@ -512,19 +517,70 @@ async function handleControlAPI(req, res, pathname, searchParams, fixtures, jour
512
517
  res.end(JSON.stringify({ error: "Invalid 'include': expected 'fixtures'" }));
513
518
  return true;
514
519
  }
520
+ const extendedTools = require_helpers.isExtendedResponsesToolsList(fixtures);
515
521
  res.writeHead(200, { "Content-Type": "application/json" });
516
522
  res.end(JSON.stringify({
517
523
  count: fixtures.length,
518
524
  fixtures: fixtures.map((fixture, index) => ({
519
525
  index,
520
526
  match: redactForInspection(fixture.match),
521
- responseKind: require_fixture_loader.isOneShotError(fixture) ? "error" : fixtureResponseKind(fixture.response),
527
+ responseKind: require_fixture_loader.isOneShotError(fixture) ? "error" : fixtureResponseKind(extendedTools || typeof fixture.response === "function" ? fixture.response : require_helpers.withoutResponsesToolKeys(fixture.response)),
522
528
  ...fixture.latency !== void 0 ? { latency: fixture.latency } : {},
523
529
  ...fixture.chaos !== void 0 ? { chaos: fixture.chaos } : {}
524
530
  }))
525
531
  }));
526
532
  return true;
527
533
  }
534
+ if (subPath === "/misbehavior/catalog" && req.method === "GET") {
535
+ res.writeHead(200, { "Content-Type": "application/json" });
536
+ res.end(JSON.stringify({
537
+ catalog: require_misbehavior.MISBEHAVIOR_CATALOG,
538
+ WIRE_SUPPORT: require_misbehavior.WIRE_SUPPORT
539
+ }));
540
+ return true;
541
+ }
542
+ if (subPath === "/misbehavior" && (req.method === "GET" || req.method === "POST" || req.method === "DELETE")) {
543
+ const scopeId = chaosScopeId(req);
544
+ if (scopeId === null) return writeBlankTestId(res);
545
+ const reply = (status, body) => {
546
+ res.writeHead(status, { "Content-Type": "application/json" });
547
+ res.end(JSON.stringify(body));
548
+ return true;
549
+ };
550
+ const scope = defaults.misbehavior;
551
+ if (!scope && req.method !== "GET") return reply(409, { error: "misbehavior is not enabled: start aimock with enableMisbehavior: true (CLI: --misbehavior)" });
552
+ if (req.method === "POST") {
553
+ let raw;
554
+ try {
555
+ raw = await require_helpers.readBody(req);
556
+ } catch (err) {
557
+ const msg = err instanceof Error ? err.message : String(err);
558
+ defaults.logger.error(`POST /__aimock/misbehavior: failed to read body: ${msg}`);
559
+ return reply(400, { error: `Failed to read request body: ${msg}` });
560
+ }
561
+ let input;
562
+ try {
563
+ input = JSON.parse(raw);
564
+ } catch (err) {
565
+ const msg = err instanceof Error ? err.message : String(err);
566
+ defaults.logger.error(`POST /__aimock/misbehavior: invalid JSON: ${msg}`);
567
+ return reply(400, { error: `Invalid JSON: ${msg}` });
568
+ }
569
+ if (require_helpers.isJsonObject(input) && Object.keys(input).length === 0) input = { faults: [] };
570
+ const parsed = require_misbehavior.parseMisbehavior(input);
571
+ if (!parsed.ok) return reply(400, {
572
+ error: "Validation failed",
573
+ rule: parsed.issue.rule,
574
+ message: parsed.issue.message
575
+ });
576
+ const config = parsed.config.seed === "random" ? {
577
+ ...parsed.config,
578
+ seed: require_misbehavior.resolveMisbehaviorSeed(parsed.config.seed, defaults.logger)
579
+ } : parsed.config;
580
+ scope?.byTestId.set(scopeId, config);
581
+ } else if (req.method === "DELETE") scope?.byTestId.delete(scopeId);
582
+ return reply(200, { misbehavior: scope?.byTestId.get(scopeId) ?? scope?.baseline ?? { faults: [] } });
583
+ }
528
584
  if (subPath === "/chaos" && req.method === "GET") {
529
585
  const scopeId = chaosScopeId(req);
530
586
  if (scopeId === null) return writeBlankTestId(res);
@@ -615,6 +671,7 @@ async function handleControlAPI(req, res, pathname, searchParams, fixtures, jour
615
671
  mounts: listed
616
672
  });
617
673
  }
674
+ if (subPath === "/mcp/fakes/report" && req.method === "GET") return require_mcp_fakes_report.handleFakesReportRoute(res, searchParams, mounts);
618
675
  if (subPath === "/fixtures" && req.method === "POST") {
619
676
  let raw;
620
677
  try {
@@ -655,8 +712,25 @@ async function handleControlAPI(req, res, pathname, searchParams, fixtures, jour
655
712
  res.end(JSON.stringify({ error: `Fixture at index ${invalidMatchIndex}: match must be an object` }));
656
713
  return true;
657
714
  }
658
- const converted = entries.map((e) => require_fixture_loader.entryToFixture(e));
659
- const errors = require_fixture_loader.validateFixtures(converted).filter((i) => i.severity === "error");
715
+ const extendedResponsesTools = defaults.responsesTools === "extended";
716
+ const markInPlace = extendedResponsesTools && require_helpers.isServerOwnedFixtures(fixtures);
717
+ const addition = controlFixtureAdditions.get(defaults) ?? 0;
718
+ controlFixtureAdditions.set(defaults, addition + 1);
719
+ const converted = [];
720
+ const loadErrors = [];
721
+ for (const [index, entry] of entries.entries()) try {
722
+ const fixture = require_fixture_loader.entryToFixture(entry, void 0, void 0, {
723
+ file: `control-api#${addition}`,
724
+ index
725
+ });
726
+ if (defaults.misbehavior) require_fixture_loader.enableHeldFixtureMisbehavior(fixture);
727
+ if (markInPlace) require_fixture_loader.markFixtureResponsesToolsExtended(fixture);
728
+ converted.push(fixture);
729
+ } catch (error) {
730
+ if (!(error instanceof require_fixture_loader.FixtureLoadError || error instanceof require_fixture_loader.MisbehaviorConfigError)) throw error;
731
+ loadErrors.push(error);
732
+ }
733
+ const errors = (loadErrors.length === 0 ? require_fixture_loader.validateFixtures(extendedResponsesTools ? converted.map(require_fixture_loader.responsesToolsExtendedView) : converted) : []).filter((i) => i.severity === "error");
660
734
  const fakes = withFakes ? planControlApiFakes(parsed.mcpFakes, mounts) : null;
661
735
  const fakeErrors = fakes?.errors ?? [];
662
736
  const validationFailed = (details) => {
@@ -667,7 +741,11 @@ async function handleControlAPI(req, res, pathname, searchParams, fixtures, jour
667
741
  }));
668
742
  return true;
669
743
  };
670
- if (errors.length > 0 || fakeErrors.length > 0) return validationFailed([...errors, ...fakeErrors.map((e) => e.toJSON())]);
744
+ if (loadErrors.length > 0 || errors.length > 0 || fakeErrors.length > 0) return validationFailed([
745
+ ...loadErrors.map((e) => e.toJSON()),
746
+ ...errors,
747
+ ...fakeErrors.map((e) => e.toJSON())
748
+ ]);
671
749
  let mcpFakesAdded = 0;
672
750
  if (fakes) try {
673
751
  mcpFakesAdded = fakes.apply({
@@ -689,6 +767,7 @@ async function handleControlAPI(req, res, pathname, searchParams, fixtures, jour
689
767
  }
690
768
  if (subPath === "/fixtures" && req.method === "DELETE") {
691
769
  require_fixture_loader.clearFixtureQueue(fixtures);
770
+ journal.clearMisbehaviorCounters();
692
771
  for (const { handler } of mounts) handler.clearMcpFakes?.();
693
772
  if (defaults.registry) defaults.registry.setGauge("aimock_fixtures_loaded", {}, fixtures.length);
694
773
  res.writeHead(200, { "Content-Type": "application/json" });
@@ -805,8 +884,9 @@ function clientAbortedMidBody(req, res, err) {
805
884
  if (err instanceof require_helpers.RequestBodyTooLargeError) return false;
806
885
  return res.destroyed && !req.complete;
807
886
  }
808
- async function handleCompletions(req, res, fixtures, journal, defaults, modelFallback, providerKey, openRouter = false) {
887
+ async function handleCompletions(req, res, fixtures, journal, defaults, getRequestEntry, modelFallback, providerKey, openRouter = false, beforeFixtureSelection, bytePlusPath = false) {
809
888
  setCorsHeaders(res);
889
+ const wire = providerKey === "azure" ? "Azure OpenAI Chat Completions" : providerKey === "openrouter" ? "OpenRouter Chat Completions" : providerKey === "byteplus" || bytePlusPath ? "BytePlus ModelArk Chat Completions" : "OpenAI Chat Completions";
810
890
  let raw;
811
891
  try {
812
892
  raw = await require_helpers.readBody(req);
@@ -972,6 +1052,7 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
972
1052
  const openRouterFallback = openRouter && Array.isArray(body.models) && body.models.length > 0;
973
1053
  const selectFixture = (probe, counts) => {
974
1054
  for (;;) {
1055
+ beforeFixtureSelection?.();
975
1056
  const attempt = require_router.matchFixtureDiagnostic(fixtures, probe, counts, defaults.requestTransform, matchOptions);
976
1057
  if (attempt.fixture && require_fixture_loader.isOneShotError(attempt.fixture) && !require_fixture_loader.claimOneShotError(fixtures, attempt.fixture)) continue;
977
1058
  return attempt;
@@ -1055,13 +1136,32 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
1055
1136
  const effectiveStrict = require_helpers.resolveStrictMode(defaults.strict, req.headers);
1056
1137
  const missWouldProxy = require_helpers.wouldProxyMiss(effectiveStrict, defaults.record, providerKey);
1057
1138
  const noFixtureSource = missWouldProxy ? "proxy" : "internal";
1139
+ const recordBypass = (reason) => {
1140
+ const entry = getRequestEntry();
1141
+ if (!entry) return;
1142
+ require_misbehavior.recordMisbehaviorOutcome({
1143
+ entry,
1144
+ summary: require_misbehavior.resolveMisbehaviorShortCircuit({
1145
+ wire: "openai-chat",
1146
+ fixture: fixture ?? void 0,
1147
+ defaults,
1148
+ rawHeaders: req.headers,
1149
+ url: req.url,
1150
+ reason
1151
+ }),
1152
+ defaults,
1153
+ testId
1154
+ });
1155
+ };
1058
1156
  if (chaosAction === "drop" || chaosAction === "disconnect" || chaosAction === "rateLimit") {
1059
1157
  require_chaos.applyChaosAction(chaosAction, res, fixture, journal, chaosContext, fixture ? "fixture" : noFixtureSource, defaults.registry, defaults.logger);
1158
+ recordBypass("chaos-fired");
1060
1159
  require_fixture_loader.releaseOneShotError(fixtures, fixture);
1061
1160
  return;
1062
1161
  }
1063
1162
  if (chaosAction === "malformed" && (fixture || !missWouldProxy)) {
1064
1163
  require_chaos.applyChaosAction(chaosAction, res, fixture, journal, chaosContext, fixture ? "fixture" : "internal", defaults.registry, defaults.logger);
1164
+ recordBypass("chaos-fired");
1065
1165
  require_fixture_loader.releaseOneShotError(fixtures, fixture);
1066
1166
  return;
1067
1167
  }
@@ -1093,6 +1193,7 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
1093
1193
  const hookOptions = chaosAction === "malformed" ? {
1094
1194
  beforeWriteResponse: () => {
1095
1195
  require_chaos.applyChaosAction(chaosAction, res, null, journal, chaosContext, "proxy", defaults.registry, defaults.logger);
1196
+ recordBypass("chaos-fired");
1096
1197
  return true;
1097
1198
  },
1098
1199
  onHookBypassed: (reason) => {
@@ -1135,10 +1236,12 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
1135
1236
  } : {}
1136
1237
  }
1137
1238
  });
1239
+ recordBypass("proxied");
1138
1240
  return;
1139
1241
  }
1140
1242
  if (chaosAction === "malformed") {
1141
1243
  require_chaos.applyChaosAction(chaosAction, res, null, journal, chaosContext, "internal", defaults.registry, defaults.logger);
1244
+ recordBypass("chaos-fired");
1142
1245
  return;
1143
1246
  }
1144
1247
  }
@@ -1161,13 +1264,71 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
1161
1264
  } }));
1162
1265
  return;
1163
1266
  }
1164
- const response = preResolvedResponse ?? await require_helpers.resolveResponse(fixture, body);
1267
+ const resolvedResponse = preResolvedResponse ?? await require_helpers.resolveResponse(fixture, body);
1268
+ const evaluation = require_misbehavior.planMisbehavior({
1269
+ wire: "openai-chat",
1270
+ fixture,
1271
+ response: resolvedResponse,
1272
+ request: body,
1273
+ stream: body.stream === true,
1274
+ defaults,
1275
+ rawHeaders: req.headers,
1276
+ url: req.url
1277
+ });
1278
+ if (evaluation.kind === "error") {
1279
+ require_misbehavior.recordMisbehaviorOutcome({
1280
+ entry: journal.add({
1281
+ method,
1282
+ path,
1283
+ headers: flatHeaders,
1284
+ body,
1285
+ response: {
1286
+ status: evaluation.status,
1287
+ fixture
1288
+ }
1289
+ }),
1290
+ summary: evaluation.summary,
1291
+ defaults,
1292
+ testId
1293
+ });
1294
+ if (!evaluation.summary?.evaluations.some((row) => row.outcome === "error")) defaults.logger.error(`${evaluation.code}: ${evaluation.message}`);
1295
+ require_sse_writer.writeErrorResponse(res, evaluation.status, openRouter ? require_openrouter_chat.serializeOpenRouterError(evaluation.status, `${evaluation.code}: ${evaluation.message}`) : JSON.stringify({ error: {
1296
+ message: evaluation.message,
1297
+ type: "invalid_request_error",
1298
+ param: null,
1299
+ code: evaluation.code
1300
+ } }));
1301
+ return;
1302
+ }
1303
+ const appliedPlan = evaluation.kind === "applied" ? require_helpers.prepareOpenAIChatMisbehavior(evaluation) : void 0;
1304
+ const response = appliedPlan?.response ?? resolvedResponse;
1305
+ const summary = appliedPlan?.summary ?? evaluation.summary;
1306
+ const recordOutcome = (entry) => {
1307
+ require_misbehavior.recordMisbehaviorOutcome({
1308
+ entry,
1309
+ summary,
1310
+ defaults,
1311
+ testId
1312
+ });
1313
+ };
1314
+ const appliedReasoning = appliedPlan && appliedPlan.reasoning === void 0 && (require_helpers.isTextResponse(response) || require_helpers.isToolCallResponse(response) || require_helpers.isCombinedFixtureResponse(response)) ? require_helpers.resolveReasoningForModel(response.reasoning, responseModel, require_helpers.resolveStrictMode(defaults.strict, req.headers), defaults.logger) : void 0;
1315
+ const appliedUsage = appliedPlan ? require_helpers.resolveOpenAIChatMisbehaviorUsage(appliedPlan, body, appliedPlan.reasoning === void 0 ? appliedReasoning !== void 0 : openRouter) : void 0;
1165
1316
  const latency = fixture.latency ?? defaults.latency;
1166
1317
  const chunkSize = Math.max(1, fixture.chunkSize ?? defaults.chunkSize);
1167
1318
  const emitStreamingUsage = body.stream === true && body.stream_options?.include_usage === true || openRouter;
1168
1319
  const streamingPromptText = body.messages.map((m) => typeof m.content === "string" ? m.content : Array.isArray(m.content) ? m.content.map((p) => p.text ?? "").join("") : "").join("");
1169
- const resolveStreamingUsageTokens = (overrides, completionText) => require_helpers.resolveUsage(overrides, streamingPromptText, completionText);
1320
+ const resolveStreamingUsageTokens = (overrides, completionText) => appliedUsage ?? require_helpers.resolveUsage(overrides, streamingPromptText, completionText);
1321
+ const resolveRecordedTimings = (chunks) => {
1322
+ const timings = fixture.recordedTimings;
1323
+ if (!appliedPlan?.duplicateId || !timings) return timings;
1324
+ const gaps = timings.interChunkDelaysMs;
1325
+ return {
1326
+ ...timings,
1327
+ interChunkDelaysMs: Array.from({ length: Math.max(gaps.length, chunks.length - 1) }, (_, index) => gaps[index] ?? gaps.at(-1) ?? 0)
1328
+ };
1329
+ };
1170
1330
  const shapeORCompletion = (completion, overrides) => {
1331
+ if (appliedUsage) completion.usage = appliedUsage;
1171
1332
  if (!openRouter) return completion;
1172
1333
  return require_openrouter_chat.shapeOpenRouterCompletion(completion, require_openrouter_chat.resolveOpenRouterShaping(overrides, overrides?.model ?? responseModel), overrides?.id !== void 0);
1173
1334
  };
@@ -1180,7 +1341,7 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
1180
1341
  const openRouterProcessing = !!(openRouter && fixture.openRouterProcessing);
1181
1342
  if (require_helpers.isErrorResponse(response)) {
1182
1343
  const status = response.status ?? 500;
1183
- journal.add({
1344
+ recordOutcome(journal.add({
1184
1345
  method: req.method ?? "POST",
1185
1346
  path: req.url ?? require_route_registry.COMPLETIONS_PATH,
1186
1347
  headers: require_helpers.flattenHeaders(req.headers),
@@ -1189,12 +1350,12 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
1189
1350
  status,
1190
1351
  fixture
1191
1352
  }
1192
- });
1353
+ }));
1193
1354
  require_sse_writer.writeErrorResponse(res, status, openRouter ? require_openrouter_chat.serializeOpenRouterError(status, response.error.message, response.error.metadata) : require_helpers.serializeErrorResponse(response), { retryAfter: response.retryAfter });
1194
1355
  return;
1195
1356
  }
1196
1357
  if (require_helpers.isAudioResponse(response)) {
1197
- journal.add({
1358
+ recordOutcome(journal.add({
1198
1359
  method: req.method ?? "POST",
1199
1360
  path: req.url ?? require_route_registry.COMPLETIONS_PATH,
1200
1361
  headers: require_helpers.flattenHeaders(req.headers),
@@ -1203,18 +1364,58 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
1203
1364
  status: 422,
1204
1365
  fixture
1205
1366
  }
1206
- });
1367
+ }));
1207
1368
  require_sse_writer.writeErrorResponse(res, 422, openRouter ? require_openrouter_chat.serializeOpenRouterError(422, "Audio responses are not supported on the chat completions endpoint. Use Gemini generateContent or a dedicated audio endpoint.") : JSON.stringify({ error: {
1208
1369
  message: "Audio responses are not supported on the chat completions endpoint. Use Gemini generateContent or a dedicated audio endpoint.",
1209
1370
  type: "invalid_request_error"
1210
1371
  } }));
1211
1372
  return;
1212
1373
  }
1213
- if (require_helpers.isContentWithToolCallsResponse(response)) {
1374
+ if (appliedPlan && require_helpers.isTextResponse(response) && (appliedPlan.stop === "refusal" || appliedPlan.stop === "content_filter" || appliedPlan.reasoning !== void 0)) {
1375
+ const overrides = require_helpers.extractOverrides(response);
1376
+ const entry = journal.add({
1377
+ method,
1378
+ path,
1379
+ headers: flatHeaders,
1380
+ body,
1381
+ response: {
1382
+ status: 200,
1383
+ fixture
1384
+ }
1385
+ });
1386
+ recordOutcome(entry);
1387
+ if (body.stream !== true) {
1388
+ const completion = appliedPlan.stop === "refusal" ? require_helpers.buildOpenAIRefusalCompletion(appliedPlan.refusal ?? "", responseModel, overrides, body.messages) : appliedPlan.stop === "content_filter" ? require_helpers.buildOpenAIContentFilterCompletion(responseModel, overrides, body.messages) : require_helpers.buildOpenAIReasoningCompletion(appliedPlan.reasoning ?? "", responseModel, openRouter, overrides, body.messages);
1389
+ res.writeHead(200, { "Content-Type": "application/json" });
1390
+ res.end(JSON.stringify(shapeORCompletion(completion, overrides)));
1391
+ } else {
1392
+ const chunks = appliedPlan.stop === "refusal" ? require_helpers.buildOpenAIRefusalChunks(appliedPlan.refusal ?? "", responseModel, chunkSize, overrides) : appliedPlan.stop === "content_filter" ? require_helpers.buildOpenAIContentFilterChunks(responseModel, overrides) : require_helpers.buildOpenAIReasoningChunks(appliedPlan.reasoning ?? "", responseModel, chunkSize, openRouter, overrides);
1393
+ const usageChunk = emitStreamingUsage ? require_helpers.buildUsageChunk(chunks[0].id, overrides?.model ?? responseModel, chunks[0].created, resolveStreamingUsageTokens(overrides, ""), overrides?.systemFingerprint) : void 0;
1394
+ shapeORChunks(chunks, usageChunk, overrides);
1395
+ const interruption = require_interruption.createInterruptionSignal(fixture);
1396
+ if (!await require_sse_writer.writeSSEStream(res, chunks, {
1397
+ latency,
1398
+ streamingProfile: fixture.streamingProfile,
1399
+ signal: interruption?.signal,
1400
+ onChunkSent: interruption?.tick,
1401
+ usageChunk,
1402
+ recordedTimings: resolveRecordedTimings(chunks),
1403
+ replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed,
1404
+ openRouterProcessing
1405
+ })) {
1406
+ if (!res.writableEnded) res.destroy();
1407
+ entry.response.interrupted = true;
1408
+ entry.response.interruptReason = interruption?.reason();
1409
+ }
1410
+ interruption?.cleanup();
1411
+ }
1412
+ return;
1413
+ }
1414
+ if (require_helpers.isCombinedFixtureResponse(response)) {
1214
1415
  if (response.webSearches?.length) defaults.logger.warn("webSearches in fixture response are not supported for Chat Completions API — ignoring");
1215
1416
  const overrides = require_helpers.extractOverrides(response);
1216
1417
  const effectiveStrict = require_helpers.resolveStrictMode(defaults.strict, req.headers);
1217
- const effReasoning = require_helpers.resolveReasoningForModel(response.reasoning, responseModel, effectiveStrict, defaults.logger);
1418
+ const effReasoning = appliedPlan ? appliedReasoning : require_helpers.resolveReasoningForModel(response.reasoning, responseModel, effectiveStrict, defaults.logger);
1218
1419
  const streaming = body.stream === true;
1219
1420
  const blockOutcome = response.blocks && response.blocks.length > 0 ? require_helpers.resolveFixtureBlockOutcome(response.blocks) : void 0;
1220
1421
  const journalEntry = journal.add({
@@ -1227,16 +1428,18 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
1227
1428
  fixture
1228
1429
  }
1229
1430
  });
1431
+ recordOutcome(journalEntry);
1432
+ const toolCalls = require_helpers.requireEmittedFunctionToolCalls(response, wire);
1230
1433
  if (!streaming) {
1231
- const completion = require_helpers.buildContentWithToolCallsCompletion(blockOutcome?.content ?? response.content ?? "", blockOutcome?.toolCalls ?? response.toolCalls ?? [], responseModel, effReasoning, blockOutcome ? {
1434
+ const completion = require_helpers.buildContentWithToolCallsCompletion(blockOutcome?.content ?? response.content ?? "", blockOutcome?.toolCalls ?? toolCalls, responseModel, effReasoning, blockOutcome ? {
1232
1435
  ...overrides,
1233
1436
  finishReason: overrides?.finishReason ?? (blockOutcome.hasToolCalls ? "tool_calls" : "stop")
1234
1437
  } : overrides, body.messages);
1235
1438
  res.writeHead(200, { "Content-Type": "application/json" });
1236
1439
  res.end(JSON.stringify(shapeORCompletion(completion, overrides)));
1237
1440
  } else {
1238
- const chunks = require_helpers.buildContentWithToolCallsChunks(blockOutcome?.content ?? response.content ?? "", blockOutcome?.toolCalls ?? response.toolCalls ?? [], responseModel, chunkSize, effReasoning, overrides, blockOutcome?.ordered);
1239
- const completionText = blockOutcome ? blockOutcome.content + blockOutcome.toolCalls.map((tc) => tc.name + tc.arguments).join("") : (response.content ?? "") + (response.toolCalls ?? []).map((tc) => tc.name + tc.arguments).join("");
1441
+ const chunks = require_helpers.buildContentWithToolCallsChunks(blockOutcome?.content ?? response.content ?? "", blockOutcome?.toolCalls ?? toolCalls, responseModel, chunkSize, effReasoning, overrides, blockOutcome?.ordered);
1442
+ const completionText = blockOutcome ? blockOutcome.content + blockOutcome.toolCalls.map((tc) => tc.name + tc.arguments).join("") : (response.content ?? "") + toolCalls.map((tc) => tc.name + tc.arguments).join("");
1240
1443
  const usageChunk = emitStreamingUsage ? require_helpers.buildUsageChunk(chunks[0]?.id ?? "chatcmpl-unknown", overrides?.model ?? responseModel, chunks[0]?.created ?? Math.floor(Date.now() / 1e3), resolveStreamingUsageTokens(overrides, completionText), overrides?.systemFingerprint) : void 0;
1241
1444
  shapeORChunks(chunks, usageChunk, overrides);
1242
1445
  const interruption = require_interruption.createInterruptionSignal(fixture);
@@ -1246,7 +1449,7 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
1246
1449
  signal: interruption?.signal,
1247
1450
  onChunkSent: interruption?.tick,
1248
1451
  usageChunk,
1249
- recordedTimings: fixture.recordedTimings,
1452
+ recordedTimings: resolveRecordedTimings(chunks),
1250
1453
  replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed,
1251
1454
  openRouterProcessing
1252
1455
  })) {
@@ -1262,7 +1465,7 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
1262
1465
  if (response.webSearches?.length) defaults.logger.warn("webSearches in fixture response are not supported for Chat Completions API — ignoring");
1263
1466
  const overrides = require_helpers.extractOverrides(response);
1264
1467
  const effectiveStrict = require_helpers.resolveStrictMode(defaults.strict, req.headers);
1265
- const effReasoning = require_helpers.resolveReasoningForModel(response.reasoning, responseModel, effectiveStrict, defaults.logger);
1468
+ const effReasoning = appliedPlan ? appliedReasoning : require_helpers.resolveReasoningForModel(response.reasoning, responseModel, effectiveStrict, defaults.logger);
1266
1469
  const journalEntry = journal.add({
1267
1470
  method: req.method ?? "POST",
1268
1471
  path: req.url ?? require_route_registry.COMPLETIONS_PATH,
@@ -1273,6 +1476,7 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
1273
1476
  fixture
1274
1477
  }
1275
1478
  });
1479
+ recordOutcome(journalEntry);
1276
1480
  if (body.stream !== true) {
1277
1481
  const completion = require_helpers.buildTextCompletion(response.content, responseModel, effReasoning, overrides, body.messages);
1278
1482
  res.writeHead(200, { "Content-Type": "application/json" });
@@ -1288,7 +1492,7 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
1288
1492
  signal: interruption?.signal,
1289
1493
  onChunkSent: interruption?.tick,
1290
1494
  usageChunk,
1291
- recordedTimings: fixture.recordedTimings,
1495
+ recordedTimings: resolveRecordedTimings(chunks),
1292
1496
  replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed,
1293
1497
  openRouterProcessing
1294
1498
  })) {
@@ -1304,7 +1508,7 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
1304
1508
  if (response.webSearches?.length) defaults.logger.warn("webSearches in fixture response are not supported for Chat Completions API — ignoring");
1305
1509
  const overrides = require_helpers.extractOverrides(response);
1306
1510
  const effectiveStrict = require_helpers.resolveStrictMode(defaults.strict, req.headers);
1307
- const effReasoning = require_helpers.resolveReasoningForModel(response.reasoning, responseModel, effectiveStrict, defaults.logger);
1511
+ const effReasoning = appliedPlan ? appliedReasoning : require_helpers.resolveReasoningForModel(response.reasoning, responseModel, effectiveStrict, defaults.logger);
1308
1512
  const journalEntry = journal.add({
1309
1513
  method: req.method ?? "POST",
1310
1514
  path: req.url ?? require_route_registry.COMPLETIONS_PATH,
@@ -1315,13 +1519,15 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
1315
1519
  fixture
1316
1520
  }
1317
1521
  });
1522
+ recordOutcome(journalEntry);
1523
+ const toolCalls = require_helpers.requireServedFunctionToolCalls(response, wire);
1318
1524
  if (body.stream !== true) {
1319
- const completion = require_helpers.buildToolCallCompletion(response.toolCalls, responseModel, effReasoning, overrides, body.messages);
1525
+ const completion = require_helpers.buildToolCallCompletion(toolCalls, responseModel, effReasoning, overrides, body.messages);
1320
1526
  res.writeHead(200, { "Content-Type": "application/json" });
1321
1527
  res.end(JSON.stringify(shapeORCompletion(completion, overrides)));
1322
1528
  } else {
1323
- const chunks = require_helpers.buildToolCallChunks(response.toolCalls, responseModel, chunkSize, effReasoning, overrides);
1324
- const completionText = response.toolCalls.map((tc) => tc.name + tc.arguments).join("");
1529
+ const chunks = require_helpers.buildToolCallChunks(toolCalls, responseModel, chunkSize, effReasoning, overrides);
1530
+ const completionText = toolCalls.map((tc) => tc.name + tc.arguments).join("");
1325
1531
  const usageChunk = emitStreamingUsage ? require_helpers.buildUsageChunk(chunks[0]?.id ?? "chatcmpl-unknown", overrides?.model ?? responseModel, chunks[0]?.created ?? Math.floor(Date.now() / 1e3), resolveStreamingUsageTokens(overrides, completionText), overrides?.systemFingerprint) : void 0;
1326
1532
  shapeORChunks(chunks, usageChunk, overrides);
1327
1533
  const interruption = require_interruption.createInterruptionSignal(fixture);
@@ -1331,7 +1537,7 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
1331
1537
  signal: interruption?.signal,
1332
1538
  onChunkSent: interruption?.tick,
1333
1539
  usageChunk,
1334
- recordedTimings: fixture.recordedTimings,
1540
+ recordedTimings: resolveRecordedTimings(chunks),
1335
1541
  replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed,
1336
1542
  openRouterProcessing
1337
1543
  })) {
@@ -1343,7 +1549,7 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
1343
1549
  }
1344
1550
  return;
1345
1551
  }
1346
- journal.add({
1552
+ recordOutcome(journal.add({
1347
1553
  method: req.method ?? "POST",
1348
1554
  path: req.url ?? require_route_registry.COMPLETIONS_PATH,
1349
1555
  headers: require_helpers.flattenHeaders(req.headers),
@@ -1352,7 +1558,7 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
1352
1558
  status: 500,
1353
1559
  fixture
1354
1560
  }
1355
- });
1561
+ }));
1356
1562
  require_sse_writer.writeErrorResponse(res, 500, openRouter ? require_openrouter_chat.serializeOpenRouterError(500, "Fixture response did not match any known type") : JSON.stringify({ error: {
1357
1563
  message: "Fixture response did not match any known type",
1358
1564
  type: "server_error"
@@ -1377,22 +1583,90 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1377
1583
  }
1378
1584
  }
1379
1585
  /**
1586
+ * The journal as JSON. An entry names the caller's fixture; the JSON shows
1587
+ * the fixture the request was served from (`Journal.servedFixture`): an
1588
+ * extended server's view, with the held keys applied, or LLMock's
1589
+ * per-addition copy with misbehavior enabled. The journal therefore reads as
1590
+ * it did when the entries held those objects.
1591
+ */
1592
+ function journalJson(entries, journal) {
1593
+ if (!entries.some((entry) => journal.servedFixture(entry) !== entry.response.fixture)) return JSON.stringify(entries);
1594
+ return JSON.stringify(entries.map((entry) => {
1595
+ const fixture = entry.response.fixture;
1596
+ let served = journal.servedFixture(entry);
1597
+ if (served === fixture || !served) return entry;
1598
+ const viewSource = require_fixture_loader.responsesToolsViewSource(served);
1599
+ if (viewSource !== served) served = require_fixture_loader.responsesToolsExtendedView(viewSource);
1600
+ return {
1601
+ ...entry,
1602
+ response: {
1603
+ ...entry.response,
1604
+ fixture: served
1605
+ }
1606
+ };
1607
+ }));
1608
+ }
1609
+ /**
1380
1610
  * The server of `createServerWithResolvedAuth`, after the MCP fakes hand-off.
1381
1611
  * `commitHandOff` runs once the server listens; if it throws, the server is
1382
1612
  * closed and start rejects.
1383
1613
  */
1384
1614
  async function startServer(fixtures, options, resolvedAuth, mountList, logger, serviceFixtures, commitHandOff) {
1615
+ const callerFixtures = fixtures;
1616
+ let rawFixtureAddition = 0;
1617
+ function ensureRawFixturePositions() {
1618
+ const existingPositions = new Set(callerFixtures.map(require_misbehavior.getFixtureMisbehaviorPosition).filter((position) => position !== void 0));
1619
+ for (const fixture of callerFixtures) {
1620
+ if (require_misbehavior.getFixtureMisbehaviorPosition(fixture) !== void 0) continue;
1621
+ let position;
1622
+ do
1623
+ position = `createServer#${rawFixtureAddition++}`;
1624
+ while (existingPositions.has(position));
1625
+ require_misbehavior.setFixtureMisbehaviorPosition(fixture, position);
1626
+ existingPositions.add(position);
1627
+ }
1628
+ }
1629
+ ensureRawFixturePositions();
1385
1630
  const host = options?.host ?? "127.0.0.1";
1386
1631
  const port = options?.port ?? 0;
1387
1632
  const registry = options?.metrics ? require_metrics.createMetricsRegistry() : void 0;
1388
1633
  const serverOptions = options ?? {};
1634
+ const validResponsesTools = (mode) => mode === "legacy" || mode === "extended";
1635
+ if (serverOptions.responsesTools !== void 0 && !validResponsesTools(serverOptions.responsesTools)) new require_logger.Logger("warn").warn(`Ignoring responsesTools because it must be "legacy" or "extended", got ${JSON.stringify(serverOptions.responsesTools)}. Using "legacy".`);
1636
+ fixtures = require_helpers.createServerFixtureList(callerFixtures, () => serverOptions.responsesTools, require_fixture_loader.responsesToolsExtendedView);
1389
1637
  const chaosByTestId = /* @__PURE__ */ new Map();
1638
+ let misbehaviorBaseline;
1639
+ const misbehavior = {
1640
+ byTestId: /* @__PURE__ */ new Map(),
1641
+ get baseline() {
1642
+ return this.byTestId.get(require_constants.DEFAULT_TEST_ID) ?? misbehaviorBaseline;
1643
+ },
1644
+ set baseline(config) {
1645
+ misbehaviorBaseline = config;
1646
+ if (config === void 0) this.byTestId.delete(require_constants.DEFAULT_TEST_ID);
1647
+ else if (this.byTestId.has(require_constants.DEFAULT_TEST_ID)) this.byTestId.set(require_constants.DEFAULT_TEST_ID, config);
1648
+ }
1649
+ };
1650
+ const misbehaviorEnabled = serverOptions.enableMisbehavior === true;
1651
+ if (misbehaviorEnabled) callerFixtures.forEach(require_fixture_loader.enableHeldFixtureMisbehavior);
1652
+ if (misbehaviorEnabled && serverOptions.misbehavior !== void 0) {
1653
+ const parsed = require_misbehavior.parseMisbehavior(serverOptions.misbehavior);
1654
+ if (!parsed.ok) throw new TypeError(`${parsed.issue.rule}: ${parsed.issue.message}`);
1655
+ misbehavior.baseline = parsed.config.seed === "random" ? {
1656
+ ...parsed.config,
1657
+ seed: require_misbehavior.resolveMisbehaviorSeed(parsed.config.seed, logger)
1658
+ } : parsed.config;
1659
+ }
1390
1660
  const defaults = {
1391
1661
  latency: serverOptions.latency ?? 0,
1392
1662
  chunkSize: Math.max(1, serverOptions.chunkSize ?? DEFAULT_CHUNK_SIZE),
1393
1663
  replaySpeed: serverOptions.replaySpeed ?? 1,
1394
1664
  logger,
1395
1665
  chaosByTestId,
1666
+ misbehavior: misbehaviorEnabled ? misbehavior : void 0,
1667
+ get misbehaviorCounters() {
1668
+ return journal;
1669
+ },
1396
1670
  get chaos() {
1397
1671
  return {
1398
1672
  base: chaosByTestId.get(require_constants.DEFAULT_TEST_ID) ?? serverOptions.chaos,
@@ -1415,6 +1689,13 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
1415
1689
  get strict() {
1416
1690
  return serverOptions.strict;
1417
1691
  },
1692
+ get strictToolArguments() {
1693
+ return serverOptions.strictToolArguments;
1694
+ },
1695
+ get responsesTools() {
1696
+ const mode = serverOptions.responsesTools;
1697
+ return validResponsesTools(mode) ? mode : void 0;
1698
+ },
1418
1699
  get requestTransform() {
1419
1700
  return serverOptions.requestTransform;
1420
1701
  },
@@ -1505,6 +1786,7 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
1505
1786
  if (req) ownJournalEntry.set(req, entry);
1506
1787
  }
1507
1788
  });
1789
+ if (serverOptions.responsesTools === "extended") journal.configureFixtureViewSource(require_fixture_loader.responsesToolsViewSource);
1508
1790
  const videoStates = new require_video.VideoStateMap();
1509
1791
  const openRouterVideoJobs = new require_openrouter_video.OpenRouterVideoJobMap();
1510
1792
  const veoVideoJobs = new require_veo_video.VeoVideoJobMap();
@@ -1519,6 +1801,85 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
1519
1801
  return status >= 400 && status < 500 ? "invalid_request_error" : "server_error";
1520
1802
  }
1521
1803
  /**
1804
+ * Envelope for a fixture tool-call error (see isFixtureToolCallError: invalid
1805
+ * JSON arguments on an object wire, a custom tool call on a non-Responses
1806
+ * wire, or a malformed fixture tool call). It is the provider envelope aimock
1807
+ * emits for that route, with the aimock `code` in it: Google's
1808
+ * `google.rpc.ErrorInfo` detail on Gemini and Vertex AI, a string
1809
+ * `error.code` on Gemini Interactions and Anthropic Messages, a `reason`
1810
+ * member on Bedrock (a `code` member would replace `__type` as the AWS SDK's
1811
+ * error name), and a sibling `code` on Ollama's bare string error. Every
1812
+ * other route, Cohere included, gets the OpenAI-style
1813
+ * `{error: {message, type, code}}`. OpenRouter routes pass their own
1814
+ * `toolCallEnvelope` instead of using this one.
1815
+ */
1816
+ function invalidToolArgumentsEnvelope(pathname, message, code) {
1817
+ if (pathname === require_route_registry.OLLAMA_CHAT_PATH) return JSON.stringify({
1818
+ error: message,
1819
+ code
1820
+ });
1821
+ if (pathname === require_route_registry.GEMINI_INTERACTIONS_PATH) return JSON.stringify({ error: {
1822
+ code,
1823
+ message
1824
+ } });
1825
+ if (require_route_registry.GEMINI_PATH_RE.test(pathname) || require_route_registry.VERTEX_AI_RE.test(pathname)) return JSON.stringify({ error: {
1826
+ code: 500,
1827
+ message,
1828
+ status: "INTERNAL",
1829
+ details: require_helpers.googleFixtureToolCallErrorDetails(code)
1830
+ } });
1831
+ if (pathname === require_route_registry.MESSAGES_PATH) return JSON.stringify({
1832
+ type: "error",
1833
+ error: {
1834
+ type: "api_error",
1835
+ code,
1836
+ message
1837
+ }
1838
+ });
1839
+ if (require_route_registry.BEDROCK_INVOKE_RE.test(pathname) || require_route_registry.BEDROCK_STREAM_RE.test(pathname) || require_route_registry.BEDROCK_CONVERSE_RE.test(pathname) || require_route_registry.BEDROCK_CONVERSE_STREAM_RE.test(pathname)) return JSON.stringify({
1840
+ __type: "InternalServerException",
1841
+ message,
1842
+ reason: code
1843
+ });
1844
+ return JSON.stringify({ error: {
1845
+ message,
1846
+ type: "server_error",
1847
+ code
1848
+ } });
1849
+ }
1850
+ function invalidMisbehaviorHeaderEnvelope(pathname, detail) {
1851
+ const code = "aimock_misbehavior_invalid";
1852
+ const message = `${code}: ${detail}`;
1853
+ if (pathname === require_route_registry.OLLAMA_CHAT_PATH || pathname === require_route_registry.OLLAMA_GENERATE_PATH) return JSON.stringify({ error: message });
1854
+ if (pathname === require_route_registry.COHERE_CHAT_PATH) return JSON.stringify({ message });
1855
+ if (pathname === require_route_registry.GEMINI_INTERACTIONS_PATH) return JSON.stringify({ error: {
1856
+ code,
1857
+ message
1858
+ } });
1859
+ if (require_route_registry.GEMINI_PATH_RE.test(pathname) || require_route_registry.VERTEX_AI_RE.test(pathname)) return JSON.stringify({ error: {
1860
+ code: 400,
1861
+ message,
1862
+ status: "INVALID_ARGUMENT"
1863
+ } });
1864
+ if (pathname === require_route_registry.MESSAGES_PATH) return JSON.stringify({
1865
+ type: "error",
1866
+ error: {
1867
+ type: "invalid_request_error",
1868
+ code,
1869
+ message
1870
+ }
1871
+ });
1872
+ if (require_route_registry.BEDROCK_INVOKE_RE.test(pathname) || require_route_registry.BEDROCK_STREAM_RE.test(pathname) || require_route_registry.BEDROCK_CONVERSE_RE.test(pathname) || require_route_registry.BEDROCK_CONVERSE_STREAM_RE.test(pathname)) return JSON.stringify({
1873
+ __type: "ValidationException",
1874
+ message
1875
+ });
1876
+ return JSON.stringify({ error: {
1877
+ message,
1878
+ type: "invalid_request_error",
1879
+ code
1880
+ } });
1881
+ }
1882
+ /**
1522
1883
  * The newest journal entry this request already produced, or null.
1523
1884
  *
1524
1885
  * Attribution is by the identity of the `IncomingMessage` the entry was
@@ -1569,6 +1930,7 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
1569
1930
  function routeError(req, res, err, pathname, opts) {
1570
1931
  const route = `${req.method ?? "?"} ${pathname}`;
1571
1932
  const msg = err instanceof Error ? err.message : "Internal error";
1933
+ const invalidToolArguments = require_helpers.isFixtureToolCallError(err);
1572
1934
  const clientFault = err instanceof require_helpers.RequestBodyTooLargeError;
1573
1935
  const clientAbort = clientAbortedMidBody(req, res, err);
1574
1936
  const status = clientFault ? 400 : 500;
@@ -1609,8 +1971,10 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
1609
1971
  return;
1610
1972
  }
1611
1973
  if (!res.headersSent) {
1612
- if (existing) existing.response.status = status;
1613
- else try {
1974
+ if (existing) {
1975
+ existing.response.status = status;
1976
+ if (invalidToolArguments) existing.response.error = msg;
1977
+ } else try {
1614
1978
  journal.add({
1615
1979
  method: req.method ?? "?",
1616
1980
  path: req.url ?? "?",
@@ -1620,14 +1984,15 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
1620
1984
  response: {
1621
1985
  status,
1622
1986
  fixture: null,
1623
- source: "internal"
1987
+ source: "internal",
1988
+ ...invalidToolArguments ? { error: msg } : {}
1624
1989
  }
1625
1990
  });
1626
1991
  } catch (jErr) {
1627
1992
  logger.warn(`${route}: journal write failed after handler error: ${jErr instanceof Error ? jErr.message : String(jErr)}`);
1628
1993
  }
1629
1994
  setCorsHeaders(res);
1630
- require_sse_writer.writeErrorResponse(res, status, opts?.envelope ? opts.envelope(msg, status) : JSON.stringify({ error: {
1995
+ require_sse_writer.writeErrorResponse(res, status, invalidToolArguments ? (opts?.toolCallEnvelope ?? ((m, c) => invalidToolArgumentsEnvelope(pathname, m, c)))(msg, require_helpers.fixtureToolCallErrorCode(err)) : opts?.envelope ? opts.envelope(msg, status) : JSON.stringify({ error: {
1631
1996
  message: msg,
1632
1997
  type: errorTypeForStatus(status)
1633
1998
  } }));
@@ -1676,13 +2041,17 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
1676
2041
  if (handler.setJournal) handler.setJournal(journal);
1677
2042
  if (registry && handler.setRegistry) handler.setRegistry(registry);
1678
2043
  if (handler.setLogger) handler.setLogger(logger);
2044
+ if (handler instanceof require_mcp_mock.MCPMock) handler.setReplaySpeed(defaults.replaySpeed);
1679
2045
  }
1680
2046
  if (registry) registry.setGauge("aimock_fixtures_loaded", {}, fixtures.length);
1681
2047
  const server = node_http.createServer((req, res) => {
1682
2048
  requestScope.run(req, () => {
1683
- handleHttpRequest(req, res).catch((err) => {
2049
+ require_helpers.runWithToolArgumentsScope({
2050
+ strict: defaults.strictToolArguments === true,
2051
+ logger
2052
+ }, () => handleHttpRequest(req, res).catch((err) => {
1684
2053
  routeError(req, res, err, req.url ?? "?");
1685
- });
2054
+ }));
1686
2055
  });
1687
2056
  });
1688
2057
  async function handleHttpRequest(req, res) {
@@ -1765,16 +2134,40 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
1765
2134
  require_api_key_auth.markAuthenticatedRequest(req, resolvedAuth.policy);
1766
2135
  }
1767
2136
  if (pathname.startsWith(require_route_registry.CONTROL_PREFIX)) {
2137
+ ensureRawFixturePositions();
1768
2138
  await handleControlAPI(req, res, pathname, parsedUrl.searchParams, fixtures, journal, videoStates, openRouterVideoJobs, veoVideoJobs, grokVideoJobs, bytePlusVideoJobs, defaults, mountList);
1769
2139
  return;
1770
2140
  }
2141
+ const misbehaviorHeader = defaults.misbehavior ? require_misbehavior.parseMisbehaviorHeader(req.headers["x-aimock-misbehavior"]) : void 0;
2142
+ if (misbehaviorHeader && !misbehaviorHeader.ok) {
2143
+ const detail = misbehaviorHeader.issue.message;
2144
+ const message = `aimock_misbehavior_invalid: ${detail}`;
2145
+ logger.error(`${req.method ?? "?"} ${pathname}: ${message}`);
2146
+ journal.add({
2147
+ method: req.method ?? "?",
2148
+ path: req.url ?? pathname,
2149
+ headers: require_helpers.flattenHeaders(req.headers),
2150
+ body: null,
2151
+ response: {
2152
+ status: 400,
2153
+ fixture: null,
2154
+ source: "internal",
2155
+ error: message
2156
+ }
2157
+ });
2158
+ setCorsHeaders(res);
2159
+ require_sse_writer.writeErrorResponse(res, 400, invalidMisbehaviorHeaderEnvelope(normalizeCompatPath(pathname), detail));
2160
+ return;
2161
+ }
1771
2162
  for (const { path: mountPath, handler } of mountList) if (pathname === mountPath || pathname.startsWith(mountPath + "/")) {
1772
2163
  const subPath = pathname.slice(mountPath.length) || "/";
1773
2164
  if (await handler.handleRequest(req, res, subPath)) return;
1774
2165
  }
1775
2166
  if (pathname === require_route_registry.OLLAMA_CHAT_PATH && req.method === "POST") {
1776
2167
  try {
1777
- await require_ollama.handleOllama(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders);
2168
+ const raw = await require_helpers.readBody(req);
2169
+ ensureRawFixturePositions();
2170
+ await require_ollama.handleOllama(req, res, raw, fixtures, journal, defaults, setCorsHeaders);
1778
2171
  } catch (err) {
1779
2172
  routeError(req, res, err, pathname);
1780
2173
  }
@@ -1782,7 +2175,9 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
1782
2175
  }
1783
2176
  if (pathname === require_route_registry.OLLAMA_GENERATE_PATH && req.method === "POST") {
1784
2177
  try {
1785
- await require_ollama.handleOllamaGenerate(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders);
2178
+ const raw = await require_helpers.readBody(req);
2179
+ ensureRawFixturePositions();
2180
+ await require_ollama.handleOllamaGenerate(req, res, raw, fixtures, journal, defaults, setCorsHeaders);
1786
2181
  } catch (err) {
1787
2182
  routeError(req, res, err, pathname);
1788
2183
  }
@@ -1790,7 +2185,9 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
1790
2185
  }
1791
2186
  if ((pathname === require_route_registry.OLLAMA_EMBEDDINGS_PATH || pathname === require_route_registry.OLLAMA_EMBED_PATH) && req.method === "POST") {
1792
2187
  try {
1793
- await require_ollama.handleOllamaEmbeddings(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders);
2188
+ const raw = await require_helpers.readBody(req);
2189
+ ensureRawFixturePositions();
2190
+ await require_ollama.handleOllamaEmbeddings(req, res, raw, fixtures, journal, defaults, setCorsHeaders);
1794
2191
  } catch (err) {
1795
2192
  routeError(req, res, err, pathname);
1796
2193
  }
@@ -1823,6 +2220,7 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
1823
2220
  }
1824
2221
  if (pathname === require_route_registry.OPENROUTER_VIDEO_MODELS_PATH && req.method === "GET") {
1825
2222
  try {
2223
+ ensureRawFixturePositions();
1826
2224
  await require_openrouter_video.handleOpenRouterVideoModels(req, res, fixtures, journal, defaults, setCorsHeaders);
1827
2225
  } catch (err) {
1828
2226
  routeError(req, res, err, pathname);
@@ -1832,6 +2230,7 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
1832
2230
  const openRouterVideoStatusMatch = pathname.match(require_route_registry.OPENROUTER_VIDEO_STATUS_RE);
1833
2231
  if (openRouterVideoStatusMatch && req.method === "GET") {
1834
2232
  try {
2233
+ ensureRawFixturePositions();
1835
2234
  await require_openrouter_video.handleOpenRouterVideoStatus(req, res, openRouterVideoStatusMatch[1], fixtures, journal, defaults, setCorsHeaders, openRouterVideoJobs);
1836
2235
  } catch (err) {
1837
2236
  routeError(req, res, err, pathname);
@@ -1841,7 +2240,9 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
1841
2240
  if (pathname === require_route_registry.OPENROUTER_VIDEOS_PATH && req.method === "POST") {
1842
2241
  setCorsHeaders(res);
1843
2242
  try {
1844
- await require_openrouter_video.handleOpenRouterVideoCreate(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders, openRouterVideoJobs);
2243
+ const raw = await require_helpers.readBody(req);
2244
+ ensureRawFixturePositions();
2245
+ await require_openrouter_video.handleOpenRouterVideoCreate(req, res, raw, fixtures, journal, defaults, setCorsHeaders, openRouterVideoJobs);
1845
2246
  } catch (err) {
1846
2247
  routeError(req, res, err, pathname);
1847
2248
  }
@@ -1850,6 +2251,7 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
1850
2251
  const bytePlusVideoStatusMatch = pathname.match(require_route_registry.BYTEPLUS_VIDEO_STATUS_RE);
1851
2252
  if (bytePlusVideoStatusMatch && req.method === "GET") {
1852
2253
  try {
2254
+ ensureRawFixturePositions();
1853
2255
  await require_byteplus_video.handleBytePlusVideoStatus(req, res, bytePlusVideoStatusMatch[1], fixtures, journal, defaults, setCorsHeaders, bytePlusVideoJobs);
1854
2256
  } catch (err) {
1855
2257
  routeError(req, res, err, pathname);
@@ -1859,13 +2261,16 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
1859
2261
  if (require_route_registry.BYTEPLUS_VIDEO_SUBMIT_RE.test(pathname) && req.method === "POST") {
1860
2262
  setCorsHeaders(res);
1861
2263
  try {
1862
- await require_byteplus_video.handleBytePlusVideoCreate(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders, bytePlusVideoJobs);
2264
+ const raw = await require_helpers.readBody(req);
2265
+ ensureRawFixturePositions();
2266
+ await require_byteplus_video.handleBytePlusVideoCreate(req, res, raw, fixtures, journal, defaults, setCorsHeaders, bytePlusVideoJobs);
1863
2267
  } catch (err) {
1864
2268
  routeError(req, res, err, pathname);
1865
2269
  }
1866
2270
  return;
1867
2271
  }
1868
2272
  if (pathname === require_route_registry.OPENROUTER_MODELS_PATH && req.method === "GET") {
2273
+ ensureRawFixturePositions();
1869
2274
  require_openrouter_chat.handleOpenRouterModels(req, res, fixtures, journal, defaults, setCorsHeaders);
1870
2275
  return;
1871
2276
  }
@@ -2204,7 +2609,7 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2204
2609
  }
2205
2610
  const entries = journal.getAll(opts);
2206
2611
  res.writeHead(200, { "Content-Type": "application/json" });
2207
- res.end(JSON.stringify(entries));
2612
+ res.end(journalJson(entries, journal));
2208
2613
  return;
2209
2614
  }
2210
2615
  if (req.method === "DELETE") {
@@ -2218,7 +2623,9 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2218
2623
  }
2219
2624
  if (pathname === require_route_registry.RESPONSES_PATH && req.method === "POST") {
2220
2625
  try {
2221
- await require_responses.handleResponses(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders);
2626
+ const raw = await require_helpers.readBody(req);
2627
+ ensureRawFixturePositions();
2628
+ await require_responses.handleResponses(req, res, raw, fixtures, journal, defaults, setCorsHeaders);
2222
2629
  } catch (err) {
2223
2630
  routeError(req, res, err, pathname, { streamEvent: (m) => `event: error\ndata: ${JSON.stringify({ error: { message: m } })}\n\n` });
2224
2631
  }
@@ -2226,7 +2633,9 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2226
2633
  }
2227
2634
  if (pathname === require_route_registry.MESSAGES_PATH && req.method === "POST") {
2228
2635
  try {
2229
- await require_messages.handleMessages(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders);
2636
+ const raw = await require_helpers.readBody(req);
2637
+ ensureRawFixturePositions();
2638
+ await require_messages.handleMessages(req, res, raw, fixtures, journal, defaults, setCorsHeaders);
2230
2639
  } catch (err) {
2231
2640
  routeError(req, res, err, pathname, { streamEvent: (m) => `event: error\ndata: ${JSON.stringify({ error: { message: m } })}\n\n` });
2232
2641
  }
@@ -2234,7 +2643,9 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2234
2643
  }
2235
2644
  if (pathname === require_route_registry.COHERE_CHAT_PATH && req.method === "POST") {
2236
2645
  try {
2237
- await require_cohere.handleCohere(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders);
2646
+ const raw = await require_helpers.readBody(req);
2647
+ ensureRawFixturePositions();
2648
+ await require_cohere.handleCohere(req, res, raw, fixtures, journal, defaults, setCorsHeaders);
2238
2649
  } catch (err) {
2239
2650
  routeError(req, res, err, pathname, { streamEvent: (m) => `event: error\ndata: ${JSON.stringify({ error: { message: m } })}\n\n` });
2240
2651
  }
@@ -2242,7 +2653,9 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2242
2653
  }
2243
2654
  if (pathname === require_route_registry.COHERE_EMBED_PATH && req.method === "POST") {
2244
2655
  try {
2245
- await require_cohere.handleCohereEmbed(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders);
2656
+ const raw = await require_helpers.readBody(req);
2657
+ ensureRawFixturePositions();
2658
+ await require_cohere.handleCohereEmbed(req, res, raw, fixtures, journal, defaults, setCorsHeaders);
2246
2659
  } catch (err) {
2247
2660
  routeError(req, res, err, pathname);
2248
2661
  }
@@ -2262,6 +2675,7 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2262
2675
  } catch (err) {
2263
2676
  if (!(err instanceof SyntaxError)) defaults.logger.error(`Unexpected error in Azure model injection: ${err instanceof Error ? err.message : String(err)}`);
2264
2677
  }
2678
+ ensureRawFixturePositions();
2265
2679
  await require_embeddings.handleEmbeddings(req, res, raw, fixtures, journal, defaults, setCorsHeaders, embeddingsProvider, originalPathname === require_route_registry.EMBEDDINGS_PATH);
2266
2680
  } catch (err) {
2267
2681
  routeError(req, res, err, pathname);
@@ -2270,7 +2684,9 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2270
2684
  }
2271
2685
  if (pathname === require_route_registry.IMAGES_PATH && req.method === "POST") {
2272
2686
  try {
2273
- await require_images.handleImages(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders, "openai", void 0, isBytePlusArk ? "byteplus" : void 0);
2687
+ const raw = await require_helpers.readBody(req);
2688
+ ensureRawFixturePositions();
2689
+ await require_images.handleImages(req, res, raw, fixtures, journal, defaults, setCorsHeaders, "openai", void 0, isBytePlusArk ? "byteplus" : void 0);
2274
2690
  } catch (err) {
2275
2691
  routeError(req, res, err, pathname);
2276
2692
  }
@@ -2278,7 +2694,9 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2278
2694
  }
2279
2695
  if (pathname === require_route_registry.IMAGES_EDIT_PATH && req.method === "POST") {
2280
2696
  try {
2281
- await require_images.handleImageEdit(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders);
2697
+ const raw = await require_helpers.readBody(req);
2698
+ ensureRawFixturePositions();
2699
+ await require_images.handleImageEdit(req, res, raw, fixtures, journal, defaults, setCorsHeaders);
2282
2700
  } catch (err) {
2283
2701
  routeError(req, res, err, pathname);
2284
2702
  }
@@ -2286,7 +2704,9 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2286
2704
  }
2287
2705
  if (pathname === require_route_registry.IMAGES_VARIATIONS_PATH && req.method === "POST") {
2288
2706
  try {
2289
- await require_images.handleImageVariations(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders);
2707
+ const raw = await require_helpers.readBody(req);
2708
+ ensureRawFixturePositions();
2709
+ await require_images.handleImageVariations(req, res, raw, fixtures, journal, defaults, setCorsHeaders);
2290
2710
  } catch (err) {
2291
2711
  routeError(req, res, err, pathname);
2292
2712
  }
@@ -2294,7 +2714,9 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2294
2714
  }
2295
2715
  if (pathname === require_route_registry.SPEECH_PATH && req.method === "POST") {
2296
2716
  try {
2297
- await require_speech.handleSpeech(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders);
2717
+ const raw = await require_helpers.readBody(req);
2718
+ ensureRawFixturePositions();
2719
+ await require_speech.handleSpeech(req, res, raw, fixtures, journal, defaults, setCorsHeaders);
2298
2720
  } catch (err) {
2299
2721
  routeError(req, res, err, pathname);
2300
2722
  }
@@ -2302,7 +2724,9 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2302
2724
  }
2303
2725
  if (pathname === require_route_registry.TRANSCRIPTIONS_PATH && req.method === "POST") {
2304
2726
  try {
2305
- await require_transcription.handleTranscription(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders);
2727
+ const raw = await require_helpers.readBody(req);
2728
+ ensureRawFixturePositions();
2729
+ await require_transcription.handleTranscription(req, res, raw, fixtures, journal, defaults, setCorsHeaders);
2306
2730
  } catch (err) {
2307
2731
  routeError(req, res, err, pathname);
2308
2732
  }
@@ -2310,7 +2734,9 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2310
2734
  }
2311
2735
  if (pathname === require_route_registry.TRANSLATIONS_PATH && req.method === "POST") {
2312
2736
  try {
2313
- await require_transcription.handleTranscription(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders, "translation");
2737
+ const raw = await require_helpers.readBody(req);
2738
+ ensureRawFixturePositions();
2739
+ await require_transcription.handleTranscription(req, res, raw, fixtures, journal, defaults, setCorsHeaders, "translation");
2314
2740
  } catch (err) {
2315
2741
  routeError(req, res, err, pathname);
2316
2742
  }
@@ -2319,7 +2745,9 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2319
2745
  if (pathname === require_route_registry.GROK_VIDEO_SUBMIT_PATH && req.method === "POST") {
2320
2746
  setCorsHeaders(res);
2321
2747
  try {
2322
- await require_grok_video.handleGrokVideoCreate(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders, grokVideoJobs);
2748
+ const raw = await require_helpers.readBody(req);
2749
+ ensureRawFixturePositions();
2750
+ await require_grok_video.handleGrokVideoCreate(req, res, raw, fixtures, journal, defaults, setCorsHeaders, grokVideoJobs);
2323
2751
  } catch (err) {
2324
2752
  routeError(req, res, err, pathname);
2325
2753
  }
@@ -2327,7 +2755,9 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2327
2755
  }
2328
2756
  if (pathname === require_route_registry.VIDEOS_PATH && req.method === "POST") {
2329
2757
  try {
2330
- await require_video.handleVideoCreate(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders, videoStates);
2758
+ const raw = await require_helpers.readBody(req);
2759
+ ensureRawFixturePositions();
2760
+ await require_video.handleVideoCreate(req, res, raw, fixtures, journal, defaults, setCorsHeaders, videoStates);
2331
2761
  } catch (err) {
2332
2762
  routeError(req, res, err, pathname);
2333
2763
  }
@@ -2336,6 +2766,7 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2336
2766
  const grokVideoStatusMatch = pathname.match(require_route_registry.GROK_VIDEO_STATUS_RE);
2337
2767
  if (grokVideoStatusMatch && grokVideoStatusMatch[1] !== "generations" && req.method === "GET") {
2338
2768
  try {
2769
+ ensureRawFixturePositions();
2339
2770
  await require_grok_video.handleGrokVideoStatus(req, res, grokVideoStatusMatch[1], fixtures, journal, defaults, setCorsHeaders, grokVideoJobs, videoStates);
2340
2771
  } catch (err) {
2341
2772
  routeError(req, res, err, pathname);
@@ -2346,7 +2777,9 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2346
2777
  if (veoPredictMatch && req.method === "POST") {
2347
2778
  setCorsHeaders(res);
2348
2779
  try {
2349
- await require_veo_video.handleVeoVideoCreate(req, res, await require_helpers.readBody(req), veoPredictMatch[1], fixtures, journal, defaults, setCorsHeaders, veoVideoJobs);
2780
+ const raw = await require_helpers.readBody(req);
2781
+ ensureRawFixturePositions();
2782
+ await require_veo_video.handleVeoVideoCreate(req, res, raw, veoPredictMatch[1], fixtures, journal, defaults, setCorsHeaders, veoVideoJobs);
2350
2783
  } catch (err) {
2351
2784
  routeError(req, res, err, pathname);
2352
2785
  }
@@ -2355,6 +2788,7 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2355
2788
  const veoOperationMatch = pathname.match(require_route_registry.VEO_OPERATION_RE);
2356
2789
  if (veoOperationMatch && req.method === "GET") {
2357
2790
  try {
2791
+ ensureRawFixturePositions();
2358
2792
  await require_veo_video.handleVeoVideoStatus(req, res, veoOperationMatch[1], fixtures, journal, defaults, setCorsHeaders, veoVideoJobs);
2359
2793
  } catch (err) {
2360
2794
  routeError(req, res, err, pathname);
@@ -2365,7 +2799,9 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2365
2799
  if (geminiPredictMatch && req.method === "POST") {
2366
2800
  const predictModel = geminiPredictMatch[1];
2367
2801
  try {
2368
- await require_images.handleImages(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders, "gemini", predictModel);
2802
+ const raw = await require_helpers.readBody(req);
2803
+ ensureRawFixturePositions();
2804
+ await require_images.handleImages(req, res, raw, fixtures, journal, defaults, setCorsHeaders, "gemini", predictModel);
2369
2805
  } catch (err) {
2370
2806
  routeError(req, res, err, pathname);
2371
2807
  }
@@ -2373,7 +2809,9 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2373
2809
  }
2374
2810
  if (pathname === require_route_registry.GEMINI_INTERACTIONS_PATH && req.method === "POST") {
2375
2811
  try {
2376
- await require_gemini_interactions.handleGeminiInteractions(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders);
2812
+ const raw = await require_helpers.readBody(req);
2813
+ ensureRawFixturePositions();
2814
+ await require_gemini_interactions.handleGeminiInteractions(req, res, raw, fixtures, journal, defaults, setCorsHeaders);
2377
2815
  } catch (err) {
2378
2816
  routeError(req, res, err, pathname, { streamEvent: (m) => `data: ${JSON.stringify({ error: { message: m } })}\n\n` });
2379
2817
  }
@@ -2383,7 +2821,9 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2383
2821
  if (geminiEmbedMatch && req.method === "POST") {
2384
2822
  const embedModel = geminiEmbedMatch[1];
2385
2823
  try {
2386
- await require_gemini_embeddings.handleGeminiEmbedContent(req, res, await require_helpers.readBody(req), embedModel, fixtures, journal, defaults, setCorsHeaders);
2824
+ const raw = await require_helpers.readBody(req);
2825
+ ensureRawFixturePositions();
2826
+ await require_gemini_embeddings.handleGeminiEmbedContent(req, res, raw, embedModel, fixtures, journal, defaults, setCorsHeaders);
2387
2827
  } catch (err) {
2388
2828
  routeError(req, res, err, pathname);
2389
2829
  }
@@ -2394,7 +2834,9 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2394
2834
  const geminiModel = geminiMatch[1];
2395
2835
  const streaming = geminiMatch[2] === "streamGenerateContent";
2396
2836
  try {
2397
- await require_gemini.handleGemini(req, res, await require_helpers.readBody(req), geminiModel, streaming, fixtures, journal, defaults, setCorsHeaders);
2837
+ const raw = await require_helpers.readBody(req);
2838
+ ensureRawFixturePositions();
2839
+ await require_gemini.handleGemini(req, res, raw, geminiModel, streaming, fixtures, journal, defaults, setCorsHeaders);
2398
2840
  } catch (err) {
2399
2841
  routeError(req, res, err, pathname, { streamEvent: (m) => `data: ${JSON.stringify({ error: { message: m } })}\n\n` });
2400
2842
  }
@@ -2405,7 +2847,9 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2405
2847
  const vertexModel = vertexMatch[1];
2406
2848
  const streaming = vertexMatch[2] === "streamGenerateContent";
2407
2849
  try {
2408
- await require_gemini.handleGemini(req, res, await require_helpers.readBody(req), vertexModel, streaming, fixtures, journal, defaults, setCorsHeaders, "vertexai");
2850
+ const raw = await require_helpers.readBody(req);
2851
+ ensureRawFixturePositions();
2852
+ await require_gemini.handleGemini(req, res, raw, vertexModel, streaming, fixtures, journal, defaults, setCorsHeaders, "vertexai");
2409
2853
  } catch (err) {
2410
2854
  routeError(req, res, err, pathname, { streamEvent: (m) => `data: ${JSON.stringify({ error: { message: m } })}\n\n` });
2411
2855
  }
@@ -2415,7 +2859,9 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2415
2859
  if (bedrockMatch && req.method === "POST") {
2416
2860
  const bedrockModelId = bedrockMatch[1];
2417
2861
  try {
2418
- await require_bedrock.handleBedrock(req, res, await require_helpers.readBody(req), bedrockModelId, fixtures, journal, defaults, setCorsHeaders);
2862
+ const raw = await require_helpers.readBody(req);
2863
+ ensureRawFixturePositions();
2864
+ await require_bedrock.handleBedrock(req, res, raw, bedrockModelId, fixtures, journal, defaults, setCorsHeaders);
2419
2865
  } catch (err) {
2420
2866
  routeError(req, res, err, pathname);
2421
2867
  }
@@ -2425,7 +2871,9 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2425
2871
  if (bedrockStreamMatch && req.method === "POST") {
2426
2872
  const bedrockModelId = bedrockStreamMatch[1];
2427
2873
  try {
2428
- await require_bedrock.handleBedrockStream(req, res, await require_helpers.readBody(req), bedrockModelId, fixtures, journal, defaults, setCorsHeaders);
2874
+ const raw = await require_helpers.readBody(req);
2875
+ ensureRawFixturePositions();
2876
+ await require_bedrock.handleBedrockStream(req, res, raw, bedrockModelId, fixtures, journal, defaults, setCorsHeaders);
2429
2877
  } catch (err) {
2430
2878
  routeError(req, res, err, pathname);
2431
2879
  }
@@ -2435,7 +2883,9 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2435
2883
  if (converseMatch && req.method === "POST") {
2436
2884
  const converseModelId = converseMatch[1];
2437
2885
  try {
2438
- await require_bedrock_converse.handleConverse(req, res, await require_helpers.readBody(req), converseModelId, fixtures, journal, defaults, setCorsHeaders);
2886
+ const raw = await require_helpers.readBody(req);
2887
+ ensureRawFixturePositions();
2888
+ await require_bedrock_converse.handleConverse(req, res, raw, converseModelId, fixtures, journal, defaults, setCorsHeaders);
2439
2889
  } catch (err) {
2440
2890
  routeError(req, res, err, pathname);
2441
2891
  }
@@ -2445,7 +2895,9 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2445
2895
  if (converseStreamMatch && req.method === "POST") {
2446
2896
  const converseStreamModelId = converseStreamMatch[1];
2447
2897
  try {
2448
- await require_bedrock_converse.handleConverseStream(req, res, await require_helpers.readBody(req), converseStreamModelId, fixtures, journal, defaults, setCorsHeaders);
2898
+ const raw = await require_helpers.readBody(req);
2899
+ ensureRawFixturePositions();
2900
+ await require_bedrock_converse.handleConverseStream(req, res, raw, converseStreamModelId, fixtures, journal, defaults, setCorsHeaders);
2449
2901
  } catch (err) {
2450
2902
  routeError(req, res, err, pathname);
2451
2903
  }
@@ -2478,7 +2930,9 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2478
2930
  if (pathname === require_route_registry.ELEVENLABS_SOUND_GENERATION_PATH && req.method === "POST") {
2479
2931
  setCorsHeaders(res);
2480
2932
  try {
2481
- await require_elevenlabs_audio.handleElevenLabsAudio(req, res, await require_helpers.readBody(req), fixtures, defaults, journal, "sound-generation");
2933
+ const raw = await require_helpers.readBody(req);
2934
+ ensureRawFixturePositions();
2935
+ await require_elevenlabs_audio.handleElevenLabsAudio(req, res, raw, fixtures, defaults, journal, "sound-generation");
2482
2936
  } catch (err) {
2483
2937
  routeError(req, res, err, pathname);
2484
2938
  }
@@ -2487,7 +2941,9 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2487
2941
  if (pathname === require_route_registry.ELEVENLABS_VOICE_DESIGN_PATH && req.method === "POST") {
2488
2942
  setCorsHeaders(res);
2489
2943
  try {
2490
- await require_elevenlabs_voice.handleElevenLabsVoiceDesign(req, res, await require_helpers.readBody(req), fixtures, defaults, journal);
2944
+ const raw = await require_helpers.readBody(req);
2945
+ ensureRawFixturePositions();
2946
+ await require_elevenlabs_voice.handleElevenLabsVoiceDesign(req, res, raw, fixtures, defaults, journal);
2491
2947
  } catch (err) {
2492
2948
  routeError(req, res, err, pathname, { service: "elevenlabs-voice" });
2493
2949
  }
@@ -2496,7 +2952,9 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2496
2952
  if (pathname === require_route_registry.ELEVENLABS_VOICE_CREATE_PATH && req.method === "POST") {
2497
2953
  setCorsHeaders(res);
2498
2954
  try {
2499
- await require_elevenlabs_voice.handleElevenLabsVoiceCreate(req, res, await require_helpers.readBody(req), fixtures, defaults, journal);
2955
+ const raw = await require_helpers.readBody(req);
2956
+ ensureRawFixturePositions();
2957
+ await require_elevenlabs_voice.handleElevenLabsVoiceCreate(req, res, raw, fixtures, defaults, journal);
2500
2958
  } catch (err) {
2501
2959
  routeError(req, res, err, pathname, { service: "elevenlabs-voice" });
2502
2960
  }
@@ -2527,8 +2985,13 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2527
2985
  return;
2528
2986
  }
2529
2987
  try {
2530
- if (req.method === "GET") await require_elevenlabs_voice.handleElevenLabsVoiceGet(req, res, voiceId, fixtures, defaults, journal);
2531
- else await require_elevenlabs_voice.handleElevenLabsVoiceDelete(req, res, voiceId, fixtures, defaults, journal);
2988
+ if (req.method === "GET") {
2989
+ ensureRawFixturePositions();
2990
+ await require_elevenlabs_voice.handleElevenLabsVoiceGet(req, res, voiceId, fixtures, defaults, journal);
2991
+ } else {
2992
+ ensureRawFixturePositions();
2993
+ await require_elevenlabs_voice.handleElevenLabsVoiceDelete(req, res, voiceId, fixtures, defaults, journal);
2994
+ }
2532
2995
  } catch (err) {
2533
2996
  routeError(req, res, err, pathname, { service: "elevenlabs-voice" });
2534
2997
  }
@@ -2539,7 +3002,9 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2539
3002
  setCorsHeaders(res);
2540
3003
  const voiceId = elevenLabsTTSMatch[1];
2541
3004
  try {
2542
- await require_elevenlabs_audio.handleElevenLabsTTS(req, res, await require_helpers.readBody(req), fixtures, defaults, journal, voiceId);
3005
+ const raw = await require_helpers.readBody(req);
3006
+ ensureRawFixturePositions();
3007
+ await require_elevenlabs_audio.handleElevenLabsTTS(req, res, raw, fixtures, defaults, journal, voiceId);
2543
3008
  } catch (err) {
2544
3009
  routeError(req, res, err, pathname);
2545
3010
  }
@@ -2550,7 +3015,9 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2550
3015
  setCorsHeaders(res);
2551
3016
  const musicSubType = musicMatch[1] ?? "music";
2552
3017
  try {
2553
- await require_elevenlabs_audio.handleElevenLabsAudio(req, res, await require_helpers.readBody(req), fixtures, defaults, journal, musicSubType);
3018
+ const raw = await require_helpers.readBody(req);
3019
+ ensureRawFixturePositions();
3020
+ await require_elevenlabs_audio.handleElevenLabsAudio(req, res, raw, fixtures, defaults, journal, musicSubType);
2554
3021
  } catch (err) {
2555
3022
  routeError(req, res, err, pathname);
2556
3023
  }
@@ -2581,6 +3048,7 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2581
3048
  return;
2582
3049
  }
2583
3050
  }
3051
+ ensureRawFixturePositions();
2584
3052
  if (await require_fal.handleFal(req, res, raw, pathname, fixtures, defaults, journal) === "handled") return;
2585
3053
  } catch (err) {
2586
3054
  routeError(req, res, err, pathname);
@@ -2590,7 +3058,9 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2590
3058
  if (pathname.match(require_route_registry.FAL_QUEUE_SUBMIT_RE) && req.method === "POST") {
2591
3059
  setCorsHeaders(res);
2592
3060
  try {
2593
- await require_fal_audio.handleFalQueue(req, res, falBody ?? await require_helpers.readBody(req), pathname, fixtures, defaults, journal);
3061
+ const raw = falBody ?? await require_helpers.readBody(req);
3062
+ ensureRawFixturePositions();
3063
+ await require_fal_audio.handleFalQueue(req, res, raw, pathname, fixtures, defaults, journal);
2594
3064
  } catch (err) {
2595
3065
  routeError(req, res, err, pathname);
2596
3066
  }
@@ -2617,6 +3087,7 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2617
3087
  }, "internal", defaults.registry, defaults.logger);
2618
3088
  return;
2619
3089
  }
3090
+ ensureRawFixturePositions();
2620
3091
  await require_fal_audio.handleFalQueue(req, res, raw, pathname, fixtures, defaults, journal);
2621
3092
  } catch (err) {
2622
3093
  routeError(req, res, err, pathname);
@@ -2626,7 +3097,9 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2626
3097
  if (pathname.match(require_route_registry.FAL_RUN_RE) && req.method === "POST") {
2627
3098
  setCorsHeaders(res);
2628
3099
  try {
2629
- await require_fal_audio.handleFalQueue(req, res, falBody ?? await require_helpers.readBody(req), pathname, fixtures, defaults, journal);
3100
+ const raw = falBody ?? await require_helpers.readBody(req);
3101
+ ensureRawFixturePositions();
3102
+ await require_fal_audio.handleFalQueue(req, res, raw, pathname, fixtures, defaults, journal);
2630
3103
  } catch (err) {
2631
3104
  routeError(req, res, err, pathname);
2632
3105
  }
@@ -2644,13 +3117,14 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2644
3117
  }
2645
3118
  const completionsProvider = azureDeploymentId ? "azure" : isOpenRouter ? "openrouter" : isBytePlusArk ? "byteplus" : "openai";
2646
3119
  try {
2647
- await handleCompletions(req, res, fixtures, journal, defaults, azureDeploymentId, completionsProvider, isOpenRouter);
3120
+ await handleCompletions(req, res, fixtures, journal, defaults, () => lastJournalEntryFor(req), azureDeploymentId, completionsProvider, isOpenRouter, ensureRawFixturePositions, originalPathname.startsWith("/api/v3/"));
2648
3121
  } catch (err) {
2649
3122
  routeError(req, res, err, pathname, {
2650
3123
  envelope: (m, status) => isOpenRouter ? require_openrouter_chat.serializeOpenRouterError(status, m) : JSON.stringify({ error: {
2651
3124
  message: m,
2652
3125
  type: errorTypeForStatus(status)
2653
3126
  } }),
3127
+ ...isOpenRouter ? { toolCallEnvelope: (m, code) => require_openrouter_chat.serializeOpenRouterError(500, m, { reason: code }) } : {},
2654
3128
  streamEvent: (m, status) => `data: ${isOpenRouter ? require_openrouter_chat.serializeOpenRouterError(status, m) : JSON.stringify({ error: {
2655
3129
  message: m,
2656
3130
  type: errorTypeForStatus(status)
@@ -2738,6 +3212,25 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2738
3212
  socket.destroy();
2739
3213
  return;
2740
3214
  }
3215
+ if (defaults.misbehavior && pathname !== require_route_registry.LIVE_PATH && req.headers["x-aimock-misbehavior"] !== void 0) {
3216
+ const code = "aimock_misbehavior_invalid";
3217
+ const message = "use the runtime scope: POST /__aimock/misbehavior with X-Test-Id";
3218
+ const body = JSON.stringify({ error: pathname === require_route_registry.GEMINI_LIVE_PATH ? {
3219
+ code: 400,
3220
+ status: "INVALID_ARGUMENT",
3221
+ message: `${code}: ${message}`
3222
+ } : {
3223
+ type: "invalid_request_error",
3224
+ code,
3225
+ message
3226
+ } });
3227
+ socket.end(`HTTP/1.1 400 Bad Request\r
3228
+ Content-Type: application/json\r
3229
+ Content-Length: ${Buffer.byteLength(body)}\r\nConnection: close\r
3230
+ \r
3231
+ ` + body);
3232
+ return;
3233
+ }
2741
3234
  let liveId;
2742
3235
  if (pathname === require_route_registry.LIVE_PATH) {
2743
3236
  if (req.method !== "GET" || parsedUrl.searchParams.has("model")) {
@@ -2799,7 +3292,8 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2799
3292
  ...defaults,
2800
3293
  model: "gpt-4",
2801
3294
  testId: wsTestId,
2802
- upgradeHeaders: req.headers
3295
+ upgradeHeaders: req.headers,
3296
+ beforeProcessMessage: ensureRawFixturePositions
2803
3297
  });
2804
3298
  else if (pathname === require_route_registry.REALTIME_PATH) {
2805
3299
  const transcriptionIntent = parsedUrl.searchParams.get("intent") === "transcription";
@@ -2809,13 +3303,15 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2809
3303
  model,
2810
3304
  transcriptionIntent,
2811
3305
  testId: wsTestId,
2812
- upgradeHeaders: req.headers
3306
+ upgradeHeaders: req.headers,
3307
+ beforeProcessMessage: ensureRawFixturePositions
2813
3308
  });
2814
3309
  } else if (pathname === require_route_registry.GEMINI_LIVE_PATH) require_ws_gemini_live.handleWebSocketGeminiLive(ws, fixtures, journal, {
2815
3310
  ...defaults,
2816
3311
  model: "gemini-2.0-flash",
2817
3312
  testId: wsTestId,
2818
- upgradeHeaders: req.headers
3313
+ upgradeHeaders: req.headers,
3314
+ beforeProcessMessage: ensureRawFixturePositions
2819
3315
  });
2820
3316
  }
2821
3317
  const originalClose = server.close.bind(server);