@copilotkit/aimock 1.46.0 → 1.47.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +12 -1
  4. package/README.md +4 -1
  5. package/dist/aws-event-stream.cjs +20 -23
  6. package/dist/aws-event-stream.cjs.map +1 -1
  7. package/dist/aws-event-stream.d.cts +0 -1
  8. package/dist/aws-event-stream.d.ts +0 -1
  9. package/dist/aws-event-stream.js +20 -24
  10. package/dist/aws-event-stream.js.map +1 -1
  11. package/dist/bedrock-converse.cjs +79 -82
  12. package/dist/bedrock-converse.cjs.map +1 -1
  13. package/dist/bedrock-converse.d.cts.map +1 -1
  14. package/dist/bedrock-converse.d.ts.map +1 -1
  15. package/dist/bedrock-converse.js +80 -83
  16. package/dist/bedrock-converse.js.map +1 -1
  17. package/dist/bedrock.cjs +112 -121
  18. package/dist/bedrock.cjs.map +1 -1
  19. package/dist/bedrock.d.cts.map +1 -1
  20. package/dist/bedrock.d.ts.map +1 -1
  21. package/dist/bedrock.js +113 -122
  22. package/dist/bedrock.js.map +1 -1
  23. package/dist/cohere.cjs +58 -106
  24. package/dist/cohere.cjs.map +1 -1
  25. package/dist/cohere.d.cts.map +1 -1
  26. package/dist/cohere.d.ts.map +1 -1
  27. package/dist/cohere.js +60 -108
  28. package/dist/cohere.js.map +1 -1
  29. package/dist/config-loader.d.cts.map +1 -1
  30. package/dist/config-loader.d.ts.map +1 -1
  31. package/dist/fixture-loader.cjs +103 -2
  32. package/dist/fixture-loader.cjs.map +1 -1
  33. package/dist/fixture-loader.d.cts.map +1 -1
  34. package/dist/fixture-loader.d.ts.map +1 -1
  35. package/dist/fixture-loader.js +104 -4
  36. package/dist/fixture-loader.js.map +1 -1
  37. package/dist/gemini-interactions.cjs +63 -121
  38. package/dist/gemini-interactions.cjs.map +1 -1
  39. package/dist/gemini-interactions.d.cts.map +1 -1
  40. package/dist/gemini-interactions.d.ts.map +1 -1
  41. package/dist/gemini-interactions.js +65 -123
  42. package/dist/gemini-interactions.js.map +1 -1
  43. package/dist/gemini.cjs +242 -155
  44. package/dist/gemini.cjs.map +1 -1
  45. package/dist/gemini.d.cts.map +1 -1
  46. package/dist/gemini.d.ts.map +1 -1
  47. package/dist/gemini.js +244 -157
  48. package/dist/gemini.js.map +1 -1
  49. package/dist/helpers.cjs +400 -7
  50. package/dist/helpers.cjs.map +1 -1
  51. package/dist/helpers.d.cts +51 -1
  52. package/dist/helpers.d.cts.map +1 -1
  53. package/dist/helpers.d.ts +51 -1
  54. package/dist/helpers.d.ts.map +1 -1
  55. package/dist/helpers.js +391 -8
  56. package/dist/helpers.js.map +1 -1
  57. package/dist/index.cjs +4 -2
  58. package/dist/index.d.cts +4 -4
  59. package/dist/index.d.ts +4 -4
  60. package/dist/index.js +4 -4
  61. package/dist/mcp-fakes.d.cts.map +1 -1
  62. package/dist/messages.cjs +159 -141
  63. package/dist/messages.cjs.map +1 -1
  64. package/dist/messages.d.cts.map +1 -1
  65. package/dist/messages.d.ts.map +1 -1
  66. package/dist/messages.js +161 -143
  67. package/dist/messages.js.map +1 -1
  68. package/dist/misbehavior.cjs +62 -3
  69. package/dist/misbehavior.cjs.map +1 -1
  70. package/dist/misbehavior.d.cts.map +1 -1
  71. package/dist/misbehavior.d.ts.map +1 -1
  72. package/dist/misbehavior.js +63 -4
  73. package/dist/misbehavior.js.map +1 -1
  74. package/dist/ndjson-writer.cjs +21 -23
  75. package/dist/ndjson-writer.cjs.map +1 -1
  76. package/dist/ndjson-writer.d.cts +0 -1
  77. package/dist/ndjson-writer.d.cts.map +1 -1
  78. package/dist/ndjson-writer.d.ts +0 -1
  79. package/dist/ndjson-writer.d.ts.map +1 -1
  80. package/dist/ndjson-writer.js +21 -24
  81. package/dist/ndjson-writer.js.map +1 -1
  82. package/dist/ollama.cjs +153 -147
  83. package/dist/ollama.cjs.map +1 -1
  84. package/dist/ollama.d.cts.map +1 -1
  85. package/dist/ollama.d.ts.map +1 -1
  86. package/dist/ollama.js +155 -149
  87. package/dist/ollama.js.map +1 -1
  88. package/dist/openrouter-chat.cjs +1 -1
  89. package/dist/openrouter-chat.js +1 -1
  90. package/dist/raw-validation.cjs +177 -0
  91. package/dist/raw-validation.cjs.map +1 -0
  92. package/dist/raw-validation.js +176 -0
  93. package/dist/raw-validation.js.map +1 -0
  94. package/dist/response/deliver.cjs +144 -0
  95. package/dist/response/deliver.cjs.map +1 -0
  96. package/dist/response/deliver.js +143 -0
  97. package/dist/response/deliver.js.map +1 -0
  98. package/dist/response/frame-loop.cjs +102 -0
  99. package/dist/response/frame-loop.cjs.map +1 -0
  100. package/dist/response/frame-loop.js +100 -0
  101. package/dist/response/frame-loop.js.map +1 -0
  102. package/dist/response/lifecycle.cjs +223 -0
  103. package/dist/response/lifecycle.cjs.map +1 -0
  104. package/dist/response/lifecycle.js +211 -0
  105. package/dist/response/lifecycle.js.map +1 -0
  106. package/dist/response/proxy.cjs +71 -0
  107. package/dist/response/proxy.cjs.map +1 -0
  108. package/dist/response/proxy.js +70 -0
  109. package/dist/response/proxy.js.map +1 -0
  110. package/dist/response/raw.cjs +228 -0
  111. package/dist/response/raw.cjs.map +1 -0
  112. package/dist/response/raw.js +227 -0
  113. package/dist/response/raw.js.map +1 -0
  114. package/dist/response/timing.cjs +157 -0
  115. package/dist/response/timing.cjs.map +1 -0
  116. package/dist/response/timing.js +150 -0
  117. package/dist/response/timing.js.map +1 -0
  118. package/dist/responses.cjs +269 -148
  119. package/dist/responses.cjs.map +1 -1
  120. package/dist/responses.d.cts.map +1 -1
  121. package/dist/responses.d.ts.map +1 -1
  122. package/dist/responses.js +270 -149
  123. package/dist/responses.js.map +1 -1
  124. package/dist/router.cjs +20 -4
  125. package/dist/router.cjs.map +1 -1
  126. package/dist/router.d.cts +7 -1
  127. package/dist/router.d.cts.map +1 -1
  128. package/dist/router.d.ts +7 -1
  129. package/dist/router.d.ts.map +1 -1
  130. package/dist/router.js +21 -5
  131. package/dist/router.js.map +1 -1
  132. package/dist/server.cjs +89 -120
  133. package/dist/server.cjs.map +1 -1
  134. package/dist/server.d.cts.map +1 -1
  135. package/dist/server.d.ts.map +1 -1
  136. package/dist/server.js +91 -122
  137. package/dist/server.js.map +1 -1
  138. package/dist/sse-writer.cjs +49 -30
  139. package/dist/sse-writer.cjs.map +1 -1
  140. package/dist/sse-writer.d.cts +0 -1
  141. package/dist/sse-writer.d.cts.map +1 -1
  142. package/dist/sse-writer.d.ts +0 -1
  143. package/dist/sse-writer.d.ts.map +1 -1
  144. package/dist/sse-writer.js +49 -31
  145. package/dist/sse-writer.js.map +1 -1
  146. package/dist/transcription.cjs +19 -33
  147. package/dist/transcription.cjs.map +1 -1
  148. package/dist/transcription.d.cts.map +1 -1
  149. package/dist/transcription.d.ts.map +1 -1
  150. package/dist/transcription.js +20 -34
  151. package/dist/transcription.js.map +1 -1
  152. package/dist/types.cjs.map +1 -1
  153. package/dist/types.d.cts +173 -10
  154. package/dist/types.d.cts.map +1 -1
  155. package/dist/types.d.ts +173 -10
  156. package/dist/types.d.ts.map +1 -1
  157. package/dist/types.js.map +1 -1
  158. package/dist/ws-framing.cjs +12 -6
  159. package/dist/ws-framing.cjs.map +1 -1
  160. package/dist/ws-framing.d.cts +2 -0
  161. package/dist/ws-framing.d.cts.map +1 -1
  162. package/dist/ws-framing.d.ts +2 -0
  163. package/dist/ws-framing.d.ts.map +1 -1
  164. package/dist/ws-framing.js +12 -6
  165. package/dist/ws-framing.js.map +1 -1
  166. package/dist/ws-gemini-live.cjs +120 -93
  167. package/dist/ws-gemini-live.cjs.map +1 -1
  168. package/dist/ws-gemini-live.js +120 -93
  169. package/dist/ws-gemini-live.js.map +1 -1
  170. package/dist/ws-realtime.cjs +80 -70
  171. package/dist/ws-realtime.cjs.map +1 -1
  172. package/dist/ws-realtime.d.cts.map +1 -1
  173. package/dist/ws-realtime.d.ts.map +1 -1
  174. package/dist/ws-realtime.js +80 -70
  175. package/dist/ws-realtime.js.map +1 -1
  176. package/dist/ws-responses.cjs +72 -53
  177. package/dist/ws-responses.cjs.map +1 -1
  178. package/dist/ws-responses.d.cts.map +1 -1
  179. package/dist/ws-responses.d.ts.map +1 -1
  180. package/dist/ws-responses.js +73 -54
  181. package/dist/ws-responses.js.map +1 -1
  182. package/package.json +1 -1
  183. package/skills/write-fixtures/SKILL.md +34 -2
package/dist/server.cjs CHANGED
@@ -15,12 +15,16 @@ const require_router = require('./router.cjs');
15
15
  const require_recorder = require('./recorder.cjs');
16
16
  const require_logger = require('./logger.cjs');
17
17
  const require_journal = require('./journal.cjs');
18
- const require_interruption = require('./interruption.cjs');
18
+ const require_lifecycle = require('./response/lifecycle.cjs');
19
+ const require_timing = require('./response/timing.cjs');
20
+ const require_deliver = require('./response/deliver.cjs');
21
+ const require_proxy = require('./response/proxy.cjs');
19
22
  const require_collect = require('./response/catalog/collect.cjs');
20
- const require_anthropic_page = require('./response/catalog/anthropic-page.cjs');
21
- const require_gemini_page = require('./response/catalog/gemini-page.cjs');
22
23
  const require_render = require('./response/catalog/render.cjs');
23
24
  const require_openrouter_chat = require('./openrouter-chat.cjs');
25
+ const require_raw = require('./response/raw.cjs');
26
+ const require_anthropic_page = require('./response/catalog/anthropic-page.cjs');
27
+ const require_gemini_page = require('./response/catalog/gemini-page.cjs');
24
28
  const require_responses = require('./responses.cjs');
25
29
  const require_messages = require('./messages.cjs');
26
30
  const require_gemini = require('./gemini.cjs');
@@ -213,6 +217,7 @@ function fixtureResponseKind(response) {
213
217
  if (require_helpers.isCombinedFixtureResponse(response)) return "contentWithToolCalls";
214
218
  if (require_helpers.isToolCallResponse(response)) return "toolCalls";
215
219
  if (require_helpers.isTextResponse(response)) return "text";
220
+ if (require_helpers.isRawResponse(response)) return "raw";
216
221
  return "unknown";
217
222
  }
218
223
  /**
@@ -898,7 +903,7 @@ async function handleCompletions(req, res, fixtures, journal, defaults, getReque
898
903
  const clientAbort = clientAbortedMidBody(req, res, err);
899
904
  const bodyLimitDisconnect = clientFault && (req.destroyed || res.destroyed);
900
905
  if (clientAbort || bodyLimitDisconnect) {
901
- const interruptReason = bodyLimitDisconnect ? "request body exceeded size limit" : "client aborted";
906
+ const interruptReason = bodyLimitDisconnect ? "request body exceeded size limit" : require_lifecycle.CLIENT_ABORTED;
902
907
  defaults.logger.warn(bodyLimitDisconnect ? `${route}: ${msg}` : `${route}: client aborted mid-body (${msg})`);
903
908
  journal.add({
904
909
  method: req.method ?? "POST",
@@ -1047,7 +1052,10 @@ async function handleCompletions(req, res, fixtures, journal, defaults, getReque
1047
1052
  body._endpointType = "chat";
1048
1053
  body._context = require_helpers.getContext(req);
1049
1054
  const testId = require_helpers.getTestId(req);
1050
- const matchOptions = require_router.recordMatchOptions(!!(defaults.record && providerKey), defaults.logger);
1055
+ const matchOptions = {
1056
+ ...require_router.recordMatchOptions(!!(defaults.record && providerKey), defaults.logger),
1057
+ wire: "openai-chat"
1058
+ };
1051
1059
  let fixture = null;
1052
1060
  let skippedBySequenceOrTurn = 0;
1053
1061
  let preResolvedResponse = null;
@@ -1077,10 +1085,11 @@ async function handleCompletions(req, res, fixtures, journal, defaults, getReque
1077
1085
  skippedBySequenceOrTurn = Math.max(skippedBySequenceOrTurn, attempt.skippedBySequenceOrTurn);
1078
1086
  if (!attempt.fixture) return null;
1079
1087
  const response = await require_helpers.resolveResponse(attempt.fixture, probe);
1088
+ const isError = require_helpers.isErrorResponse(response) || require_helpers.isRawResponse(response) && (response.raw.status ?? 200) >= 400;
1080
1089
  return {
1081
1090
  fixture: attempt.fixture,
1082
1091
  response,
1083
- isError: require_helpers.isErrorResponse(response)
1092
+ isError
1084
1093
  };
1085
1094
  };
1086
1095
  for (const candidate of candidates) {
@@ -1094,7 +1103,7 @@ async function handleCompletions(req, res, fixtures, journal, defaults, getReque
1094
1103
  matchCounts = journal.getFixtureMatchCountsForTest(testId);
1095
1104
  responseModel = candidate;
1096
1105
  if (outcome.isError) {
1097
- const errorFallsThrough = outcome.response.fallthrough !== false;
1106
+ const errorFallsThrough = !require_helpers.isErrorResponse(outcome.response) || outcome.response.fallthrough !== false;
1098
1107
  if (allowFallbacks && errorFallsThrough) {
1099
1108
  lastErrorFixture = outcome.fixture;
1100
1109
  lastErrorResponse = outcome.response;
@@ -1211,22 +1220,9 @@ async function handleCompletions(req, res, fixtures, journal, defaults, getReque
1211
1220
  });
1212
1221
  }
1213
1222
  } : void 0;
1214
- let clientHungUp = false;
1215
- const noteClientHangUp = () => {
1216
- if (!res.writableEnded) clientHungUp = true;
1217
- };
1218
- req.socket?.on("end", noteClientHangUp);
1219
- req.socket?.on("error", noteClientHangUp);
1220
- let outcome;
1221
- try {
1222
- outcome = await require_recorder.proxyAndRecord(req, res, body, providerKey, req.url ?? require_route_registry.COMPLETIONS_PATH, fixtures, defaults, raw, hookOptions);
1223
- } finally {
1224
- req.socket?.off("end", noteClientHangUp);
1225
- req.socket?.off("error", noteClientHangUp);
1226
- }
1223
+ const { outcome, clientHungUp } = await require_proxy.withHangUpDetection(req, res, () => require_recorder.proxyAndRecord(req, res, body, providerKey, req.url ?? require_route_registry.COMPLETIONS_PATH, fixtures, defaults, raw, hookOptions));
1227
1224
  if (outcome === "handled_by_hook") return;
1228
1225
  if (outcome !== "not_configured") {
1229
- const destroyedMidStream = res.destroyed && !res.writableEnded;
1230
1226
  journal.add({
1231
1227
  method: req.method ?? "POST",
1232
1228
  path: req.url ?? require_route_registry.COMPLETIONS_PATH,
@@ -1236,10 +1232,7 @@ async function handleCompletions(req, res, fixtures, journal, defaults, getReque
1236
1232
  status: res.statusCode ?? 200,
1237
1233
  fixture: null,
1238
1234
  source: "proxy",
1239
- ...destroyedMidStream ? {
1240
- interrupted: true,
1241
- interruptReason: clientHungUp ? "client aborted" : "proxy stream destroyed"
1242
- } : {}
1235
+ ...require_proxy.proxyInterruption(res, clientHungUp)
1243
1236
  }
1244
1237
  });
1245
1238
  recordBypass("proxied");
@@ -1326,20 +1319,23 @@ async function handleCompletions(req, res, fixtures, journal, defaults, getReque
1326
1319
  const emitStreamingUsage = body.stream === true && body.stream_options?.include_usage === true || openRouter;
1327
1320
  const streamingPromptText = body.messages.map((m) => typeof m.content === "string" ? m.content : Array.isArray(m.content) ? m.content.map((p) => p.text ?? "").join("") : "").join("");
1328
1321
  const resolveStreamingUsageTokens = (overrides, completionText) => appliedUsage ?? require_helpers.resolveUsage(overrides, streamingPromptText, completionText);
1329
- const resolveRecordedTimings = (chunkCount) => {
1330
- const timings = fixture.recordedTimings;
1331
- if (!appliedPlan?.duplicateId || !timings) return timings;
1332
- const gaps = timings.interChunkDelaysMs;
1333
- return {
1334
- ...timings,
1335
- interChunkDelaysMs: Array.from({ length: Math.max(gaps.length, chunkCount - 1) }, (_, index) => gaps[index] ?? gaps.at(-1) ?? 0)
1336
- };
1337
- };
1338
- const awaitNonStreamingTiming = (contentLength) => {
1339
- if (fixture.nonStreamingTiming !== true) return Promise.resolve();
1340
- if (!fixture.streamingProfile && !fixture.recordedTimings) return Promise.resolve();
1341
- const chunkCount = Math.max(1, Math.ceil(contentLength / chunkSize));
1342
- return require_sse_writer.delay(require_sse_writer.calculateTotalDelay(contentLength, chunkSize, fixture.streamingProfile, resolveRecordedTimings(chunkCount), fixture.replaySpeed ?? defaults.replaySpeed));
1322
+ const nonStreamingOpts = (payloadLength) => ({
1323
+ surface: "openai-chat",
1324
+ payloadLength,
1325
+ chunkSize,
1326
+ recordedTimings: fixture.recordedTimings,
1327
+ duplicateId: !!appliedPlan?.duplicateId,
1328
+ replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed
1329
+ });
1330
+ const streamTiming = (frameCount) => ({
1331
+ latency,
1332
+ streamingProfile: fixture.streamingProfile,
1333
+ recordedTimings: require_timing.extendRecordedTimings(fixture.recordedTimings, frameCount, !!appliedPlan?.duplicateId),
1334
+ replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed
1335
+ });
1336
+ const commitNonStream = async (entry, reply, payloadLength) => {
1337
+ recordOutcome(entry);
1338
+ await require_deliver.deliverJson(res, entry, fixture, () => reply, nonStreamingOpts(payloadLength));
1343
1339
  };
1344
1340
  const shapeORCompletion = (completion, overrides) => {
1345
1341
  if (appliedUsage) completion.usage = appliedUsage;
@@ -1353,6 +1349,24 @@ async function handleCompletions(req, res, fixtures, journal, defaults, getReque
1353
1349
  if (usageChunk) require_openrouter_chat.shapeOpenRouterChunks([usageChunk], shaping, overrides?.id !== void 0);
1354
1350
  };
1355
1351
  const openRouterProcessing = !!(openRouter && fixture.openRouterProcessing);
1352
+ if (require_helpers.isRawResponse(response)) {
1353
+ await require_raw.serveRawResponse({
1354
+ wire: "openai-chat",
1355
+ stream: body.stream === true,
1356
+ req,
1357
+ res,
1358
+ fixture,
1359
+ response,
1360
+ body,
1361
+ journal,
1362
+ defaults,
1363
+ testId,
1364
+ misbehaviorSummary: evaluation.summary,
1365
+ errorWire: "openai",
1366
+ openRouter
1367
+ });
1368
+ return;
1369
+ }
1356
1370
  if (require_helpers.isErrorResponse(response)) {
1357
1371
  const status = response.status ?? 500;
1358
1372
  recordOutcome(journal.add({
@@ -1397,32 +1411,18 @@ async function handleCompletions(req, res, fixtures, journal, defaults, getReque
1397
1411
  fixture
1398
1412
  }
1399
1413
  });
1400
- recordOutcome(entry);
1401
- if (body.stream !== true) {
1402
- 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);
1403
- await awaitNonStreamingTiming((appliedPlan.stop === "refusal" ? appliedPlan.refusal ?? "" : appliedPlan.stop === "content_filter" ? "" : appliedPlan.reasoning ?? "").length);
1404
- res.writeHead(200, { "Content-Type": "application/json" });
1405
- res.end(JSON.stringify(shapeORCompletion(completion, overrides)));
1406
- } else {
1414
+ require_helpers.rejectGeneratedFiles(response, wire);
1415
+ if (body.stream !== true) await commitNonStream(entry, shapeORCompletion(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), overrides), require_timing.misbehaviorPayloadLength(appliedPlan, appliedReasoning));
1416
+ else {
1407
1417
  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);
1408
1418
  const usageChunk = emitStreamingUsage ? require_helpers.buildUsageChunk(chunks[0].id, overrides?.model ?? responseModel, chunks[0].created, resolveStreamingUsageTokens(overrides, ""), overrides?.systemFingerprint) : void 0;
1409
1419
  shapeORChunks(chunks, usageChunk, overrides);
1410
- const interruption = require_interruption.createInterruptionSignal(fixture);
1411
- if (!await require_sse_writer.writeSSEStream(res, chunks, {
1412
- latency,
1413
- streamingProfile: fixture.streamingProfile,
1414
- signal: interruption?.signal,
1415
- onChunkSent: interruption?.tick,
1420
+ recordOutcome(entry);
1421
+ await require_deliver.deliverStream(res, entry, fixture, require_sse_writer.sseCodec({
1422
+ done: true,
1416
1423
  usageChunk,
1417
- recordedTimings: resolveRecordedTimings(chunks.length),
1418
- replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed,
1419
1424
  openRouterProcessing
1420
- })) {
1421
- if (!res.writableEnded) res.destroy();
1422
- entry.response.interrupted = true;
1423
- entry.response.interruptReason = interruption?.reason();
1424
- }
1425
- interruption?.cleanup();
1425
+ }), chunks, streamTiming(chunks.length));
1426
1426
  }
1427
1427
  return;
1428
1428
  }
@@ -1443,37 +1443,26 @@ async function handleCompletions(req, res, fixtures, journal, defaults, getReque
1443
1443
  fixture
1444
1444
  }
1445
1445
  });
1446
- recordOutcome(journalEntry);
1446
+ require_helpers.rejectGeneratedFiles(response, wire);
1447
1447
  const toolCalls = require_helpers.requireEmittedFunctionToolCalls(response, wire);
1448
1448
  const completionText = blockOutcome ? blockOutcome.content + blockOutcome.toolCalls.map((tc) => tc.name + tc.arguments).join("") : (response.content ?? "") + toolCalls.map((tc) => tc.name + tc.arguments).join("");
1449
1449
  if (!streaming) {
1450
- await awaitNonStreamingTiming((effReasoning?.length ?? 0) + completionText.length);
1451
1450
  const completion = require_helpers.buildContentWithToolCallsCompletion(blockOutcome?.content ?? response.content ?? "", blockOutcome?.toolCalls ?? toolCalls, responseModel, effReasoning, blockOutcome ? {
1452
1451
  ...overrides,
1453
1452
  finishReason: overrides?.finishReason ?? (blockOutcome.hasToolCalls ? "tool_calls" : "stop")
1454
1453
  } : overrides, body.messages);
1455
- res.writeHead(200, { "Content-Type": "application/json" });
1456
- res.end(JSON.stringify(shapeORCompletion(completion, overrides)));
1454
+ const contentLength = (effReasoning?.length ?? 0) + completionText.length;
1455
+ await commitNonStream(journalEntry, shapeORCompletion(completion, overrides), contentLength);
1457
1456
  } else {
1458
1457
  const chunks = require_helpers.buildContentWithToolCallsChunks(blockOutcome?.content ?? response.content ?? "", blockOutcome?.toolCalls ?? toolCalls, responseModel, chunkSize, effReasoning, overrides, blockOutcome?.ordered);
1459
1458
  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;
1460
1459
  shapeORChunks(chunks, usageChunk, overrides);
1461
- const interruption = require_interruption.createInterruptionSignal(fixture);
1462
- if (!await require_sse_writer.writeSSEStream(res, chunks, {
1463
- latency,
1464
- streamingProfile: fixture.streamingProfile,
1465
- signal: interruption?.signal,
1466
- onChunkSent: interruption?.tick,
1460
+ recordOutcome(journalEntry);
1461
+ await require_deliver.deliverStream(res, journalEntry, fixture, require_sse_writer.sseCodec({
1462
+ done: true,
1467
1463
  usageChunk,
1468
- recordedTimings: resolveRecordedTimings(chunks.length),
1469
- replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed,
1470
1464
  openRouterProcessing
1471
- })) {
1472
- if (!res.writableEnded) res.destroy();
1473
- journalEntry.response.interrupted = true;
1474
- journalEntry.response.interruptReason = interruption?.reason();
1475
- }
1476
- interruption?.cleanup();
1465
+ }), chunks, streamTiming(chunks.length));
1477
1466
  }
1478
1467
  return;
1479
1468
  }
@@ -1492,32 +1481,21 @@ async function handleCompletions(req, res, fixtures, journal, defaults, getReque
1492
1481
  fixture
1493
1482
  }
1494
1483
  });
1495
- recordOutcome(journalEntry);
1484
+ require_helpers.rejectGeneratedFiles(response, wire);
1496
1485
  if (body.stream !== true) {
1497
- await awaitNonStreamingTiming((effReasoning?.length ?? 0) + response.content.length);
1498
1486
  const completion = require_helpers.buildTextCompletion(response.content, responseModel, effReasoning, overrides, body.messages);
1499
- res.writeHead(200, { "Content-Type": "application/json" });
1500
- res.end(JSON.stringify(shapeORCompletion(completion, overrides)));
1487
+ const contentLength = (effReasoning?.length ?? 0) + response.content.length;
1488
+ await commitNonStream(journalEntry, shapeORCompletion(completion, overrides), contentLength);
1501
1489
  } else {
1502
1490
  const chunks = require_helpers.buildTextChunks(response.content, responseModel, chunkSize, effReasoning, overrides);
1503
1491
  const usageChunk = emitStreamingUsage ? require_helpers.buildUsageChunk(chunks[0]?.id ?? "chatcmpl-unknown", overrides?.model ?? responseModel, chunks[0]?.created ?? Math.floor(Date.now() / 1e3), resolveStreamingUsageTokens(overrides, response.content), overrides?.systemFingerprint) : void 0;
1504
1492
  shapeORChunks(chunks, usageChunk, overrides);
1505
- const interruption = require_interruption.createInterruptionSignal(fixture);
1506
- if (!await require_sse_writer.writeSSEStream(res, chunks, {
1507
- latency,
1508
- streamingProfile: fixture.streamingProfile,
1509
- signal: interruption?.signal,
1510
- onChunkSent: interruption?.tick,
1493
+ recordOutcome(journalEntry);
1494
+ await require_deliver.deliverStream(res, journalEntry, fixture, require_sse_writer.sseCodec({
1495
+ done: true,
1511
1496
  usageChunk,
1512
- recordedTimings: resolveRecordedTimings(chunks.length),
1513
- replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed,
1514
1497
  openRouterProcessing
1515
- })) {
1516
- if (!res.writableEnded) res.destroy();
1517
- journalEntry.response.interrupted = true;
1518
- journalEntry.response.interruptReason = interruption?.reason();
1519
- }
1520
- interruption?.cleanup();
1498
+ }), chunks, streamTiming(chunks.length));
1521
1499
  }
1522
1500
  return;
1523
1501
  }
@@ -1536,35 +1514,24 @@ async function handleCompletions(req, res, fixtures, journal, defaults, getReque
1536
1514
  fixture
1537
1515
  }
1538
1516
  });
1539
- recordOutcome(journalEntry);
1517
+ require_helpers.rejectGeneratedFiles(response, wire);
1540
1518
  const toolCalls = require_helpers.requireServedFunctionToolCalls(response, wire);
1541
1519
  if (body.stream !== true) {
1542
1520
  const toolCallText = toolCalls.map((tc) => tc.name + tc.arguments).join("");
1543
- await awaitNonStreamingTiming((effReasoning?.length ?? 0) + toolCallText.length);
1544
1521
  const completion = require_helpers.buildToolCallCompletion(toolCalls, responseModel, effReasoning, overrides, body.messages);
1545
- res.writeHead(200, { "Content-Type": "application/json" });
1546
- res.end(JSON.stringify(shapeORCompletion(completion, overrides)));
1522
+ const contentLength = (effReasoning?.length ?? 0) + toolCallText.length;
1523
+ await commitNonStream(journalEntry, shapeORCompletion(completion, overrides), contentLength);
1547
1524
  } else {
1548
1525
  const chunks = require_helpers.buildToolCallChunks(toolCalls, responseModel, chunkSize, effReasoning, overrides);
1549
1526
  const completionText = toolCalls.map((tc) => tc.name + tc.arguments).join("");
1550
1527
  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;
1551
1528
  shapeORChunks(chunks, usageChunk, overrides);
1552
- const interruption = require_interruption.createInterruptionSignal(fixture);
1553
- if (!await require_sse_writer.writeSSEStream(res, chunks, {
1554
- latency,
1555
- streamingProfile: fixture.streamingProfile,
1556
- signal: interruption?.signal,
1557
- onChunkSent: interruption?.tick,
1529
+ recordOutcome(journalEntry);
1530
+ await require_deliver.deliverStream(res, journalEntry, fixture, require_sse_writer.sseCodec({
1531
+ done: true,
1558
1532
  usageChunk,
1559
- recordedTimings: resolveRecordedTimings(chunks.length),
1560
- replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed,
1561
1533
  openRouterProcessing
1562
- })) {
1563
- if (!res.writableEnded) res.destroy();
1564
- journalEntry.response.interrupted = true;
1565
- journalEntry.response.interruptReason = interruption?.reason();
1566
- }
1567
- interruption?.cleanup();
1534
+ }), chunks, streamTiming(chunks.length));
1568
1535
  }
1569
1536
  return;
1570
1537
  }
@@ -1824,10 +1791,12 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
1824
1791
  return status >= 400 && status < 500 ? "invalid_request_error" : "server_error";
1825
1792
  }
1826
1793
  /**
1827
- * Envelope for a fixture tool-call error (see isFixtureToolCallError: invalid
1828
- * JSON arguments on an object wire, a custom tool call on a non-Responses
1829
- * wire, or a malformed fixture tool call). It is the provider envelope aimock
1830
- * emits for that route, with the aimock `code` in it: Google's
1794
+ * Envelope for a fixture error (see isFixtureToolCallError: invalid JSON
1795
+ * arguments on an object wire, a custom tool call on a non-Responses wire, a
1796
+ * malformed fixture tool call, generated `files` on a wire that cannot carry
1797
+ * them, or a malformed fixture `citations` or `files` value). It is the
1798
+ * provider envelope aimock emits for that route, with the aimock `code` in
1799
+ * it: Google's
1831
1800
  * `google.rpc.ErrorInfo` detail on Gemini and Vertex AI, a string
1832
1801
  * `error.code` on Gemini Interactions and Anthropic Messages, a `reason`
1833
1802
  * member on Bedrock (a `code` member would replace `__type` as the AWS SDK's
@@ -1957,7 +1926,7 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
1957
1926
  const existing = lastJournalEntryFor(req);
1958
1927
  const bodyLimitDisconnect = clientFault && (req.destroyed || res.destroyed);
1959
1928
  if ((clientAbort || bodyLimitDisconnect) && !res.headersSent) {
1960
- const interruptReason = bodyLimitDisconnect ? "request body exceeded size limit" : "client aborted";
1929
+ const interruptReason = bodyLimitDisconnect ? "request body exceeded size limit" : require_lifecycle.CLIENT_ABORTED;
1961
1930
  if (existing) {
1962
1931
  if (!existing.response.interrupted) {
1963
1932
  existing.response.status = 0;
@@ -2013,7 +1982,7 @@ async function startServer(fixtures, options, resolvedAuth, mountList, logger, s
2013
1982
  type: errorTypeForStatus(status)
2014
1983
  }).body);
2015
1984
  } else {
2016
- const midStreamReason = clientAbort ? "client aborted" : "handler crashed mid-stream";
1985
+ const midStreamReason = clientAbort ? require_lifecycle.CLIENT_ABORTED : "handler crashed mid-stream";
2017
1986
  if (existing) {
2018
1987
  if (res.writableEnded) {
2019
1988
  if (existing.response.error === void 0) existing.response.error = msg;