@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/bedrock.cjs CHANGED
@@ -7,10 +7,13 @@ const require_misbehavior = require('./misbehavior.cjs');
7
7
  const require_router = require('./router.cjs');
8
8
  const require_anthropic = require('./response/usage/codecs/anthropic.cjs');
9
9
  const require_recorder = require('./recorder.cjs');
10
- const require_interruption = require('./interruption.cjs');
10
+ const require_timing = require('./response/timing.cjs');
11
+ const require_deliver = require('./response/deliver.cjs');
12
+ const require_proxy = require('./response/proxy.cjs');
13
+ const require_aws_event_stream = require('./aws-event-stream.cjs');
14
+ const require_raw = require('./response/raw.cjs');
11
15
  const require_finish = require('./response/finish.cjs');
12
16
  const require_messages = require('./messages.cjs');
13
- const require_aws_event_stream = require('./aws-event-stream.cjs');
14
17
 
15
18
  //#region src/bedrock.ts
16
19
  function bedrockStopReason(overrideFinishReason, defaultReason) {
@@ -266,7 +269,10 @@ async function handleBedrock(req, res, raw, modelId, fixtures, journal, defaults
266
269
  completionReq._endpointType = "chat";
267
270
  completionReq._context = require_helpers.getContext(req);
268
271
  const testId = require_helpers.getTestId(req);
269
- const { fixture, skippedBySequenceOrTurn } = require_router.matchFixtureDiagnostic(fixtures, completionReq, journal.getFixtureMatchCountsForTest(testId), defaults.requestTransform, require_router.recordMatchOptions(!!defaults.record, defaults.logger));
272
+ const { fixture, skippedBySequenceOrTurn } = require_router.matchFixtureDiagnostic(fixtures, completionReq, journal.getFixtureMatchCountsForTest(testId), defaults.requestTransform, {
273
+ ...require_router.recordMatchOptions(!!defaults.record, defaults.logger),
274
+ wire: "bedrock-invoke"
275
+ });
270
276
  if (fixture) logger.debug(`Fixture matched: ${JSON.stringify(fixture.match).slice(0, 120)}`);
271
277
  else logger.debug(`No fixture matched for request`);
272
278
  if (fixture) journal.incrementFixtureMatchCount(fixture, fixtures, testId);
@@ -299,7 +305,7 @@ async function handleBedrock(req, res, raw, modelId, fixtures, journal, defaults
299
305
  return;
300
306
  }
301
307
  if (defaults.record) {
302
- const outcome = await require_recorder.proxyAndRecord(req, res, completionReq, "bedrock", urlPath, fixtures, defaults, raw);
308
+ const { outcome, clientHungUp } = await require_proxy.withHangUpDetection(req, res, () => require_recorder.proxyAndRecord(req, res, completionReq, "bedrock", urlPath, fixtures, defaults, raw));
303
309
  if (outcome === "handled_by_hook") return;
304
310
  if (outcome !== "not_configured") {
305
311
  journal.add({
@@ -310,7 +316,8 @@ async function handleBedrock(req, res, raw, modelId, fixtures, journal, defaults
310
316
  response: {
311
317
  status: res.statusCode ?? 200,
312
318
  fixture: null,
313
- source: "proxy"
319
+ source: "proxy",
320
+ ...require_proxy.proxyInterruption(res, clientHungUp)
314
321
  }
315
322
  });
316
323
  return;
@@ -376,32 +383,60 @@ async function handleBedrock(req, res, raw, modelId, fixtures, journal, defaults
376
383
  require_sse_writer.writeErrorResponse(res, misbehavior.status, renderedError.body);
377
384
  return;
378
385
  }
386
+ const chunkSize = Math.max(1, fixture.chunkSize ?? defaults.chunkSize);
387
+ const jsonOpts = (payloadLength, duplicateId = false) => ({
388
+ surface: "other",
389
+ payloadLength,
390
+ chunkSize,
391
+ recordedTimings: fixture.recordedTimings,
392
+ duplicateId,
393
+ replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed
394
+ });
379
395
  if (misbehavior.kind === "applied") {
380
396
  const prepared = require_messages.prepareClaudeMisbehavior(misbehavior, {
381
397
  request: completionReq,
382
398
  stream: false,
383
- chunkSize: Math.max(1, fixture.chunkSize ?? defaults.chunkSize),
399
+ chunkSize,
384
400
  logger,
385
- strict: require_policy.resolveRequestDecisions(defaults.strict, req.headers).reasoningSuppression
401
+ strict: require_policy.resolveRequestDecisions(defaults.strict, req.headers).reasoningSuppression,
402
+ citations: false
386
403
  });
387
404
  if (prepared.stream) throw new TypeError("InvokeModel requires non-stream Claude output");
405
+ const entry = journal.add({
406
+ method: req.method ?? "POST",
407
+ path: urlPath,
408
+ headers: require_helpers.flattenHeaders(req.headers),
409
+ body: completionReq,
410
+ response: {
411
+ status: 200,
412
+ fixture
413
+ }
414
+ });
388
415
  require_misbehavior.recordMisbehaviorOutcome({
389
- entry: journal.add({
390
- method: req.method ?? "POST",
391
- path: urlPath,
392
- headers: require_helpers.flattenHeaders(req.headers),
393
- body: completionReq,
394
- response: {
395
- status: 200,
396
- fixture
397
- }
398
- }),
416
+ entry,
399
417
  summary: prepared.plan.summary,
400
418
  defaults,
401
419
  testId
402
420
  });
403
- res.writeHead(200, { "Content-Type": "application/json" });
404
- res.end(JSON.stringify(prepared.body));
421
+ const preparedBody = prepared.body;
422
+ await require_deliver.deliverJson(res, entry, fixture, () => preparedBody, jsonOpts(require_timing.misbehaviorPayloadLength(misbehavior, misbehavior.reasoning === void 0 ? prepared.reasoning : void 0), !!misbehavior.duplicateId));
423
+ return;
424
+ }
425
+ if (require_helpers.isRawResponse(response)) {
426
+ await require_raw.serveRawResponse({
427
+ wire: "bedrock-invoke",
428
+ stream: false,
429
+ req,
430
+ res,
431
+ fixture,
432
+ response,
433
+ body: completionReq,
434
+ journal,
435
+ defaults,
436
+ testId,
437
+ misbehaviorSummary: misbehavior.summary,
438
+ errorWire: "bedrock"
439
+ });
405
440
  return;
406
441
  }
407
442
  if (require_helpers.isErrorResponse(response)) {
@@ -423,7 +458,7 @@ async function handleBedrock(req, res, raw, modelId, fixtures, journal, defaults
423
458
  if (response.webSearches?.length) logger.warn("webSearches in fixture response are not supported for Bedrock API — ignoring");
424
459
  const overrides = require_helpers.extractOverrides(response);
425
460
  const effReasoning = require_helpers.resolveReasoningForModel(response.reasoning, completionReq.model, require_policy.resolveRequestDecisions(defaults.strict, req.headers).reasoningSuppression, logger);
426
- addResponseEntry({
461
+ const journalEntry = addResponseEntry({
427
462
  method: req.method ?? "POST",
428
463
  path: urlPath,
429
464
  headers: require_helpers.flattenHeaders(req.headers),
@@ -434,28 +469,27 @@ async function handleBedrock(req, res, raw, modelId, fixtures, journal, defaults
434
469
  }
435
470
  });
436
471
  const functionToolCalls = require_helpers.requireEmittedFunctionToolCalls(response, "Bedrock InvokeModel");
437
- if (response.blocks && response.blocks.length > 0) {
438
- const blocksBody = buildBedrockBlocksResponse(response.blocks, completionReq.model, logger, effReasoning, overrides);
439
- res.writeHead(200, { "Content-Type": "application/json" });
440
- res.end(JSON.stringify(blocksBody));
472
+ const blocks = response.blocks;
473
+ if (blocks && blocks.length > 0) {
474
+ await require_deliver.deliverJson(res, journalEntry, fixture, () => buildBedrockBlocksResponse(blocks, completionReq.model, logger, effReasoning, overrides), jsonOpts(require_timing.servedPayloadLength(response, effReasoning)));
441
475
  return;
442
476
  }
443
- const textBody = buildBedrockTextResponse(response.content ?? "", completionReq.model, effReasoning, overrides);
444
- const toolBody = buildBedrockToolCallResponse(functionToolCalls, completionReq.model, logger, void 0, overrides);
445
- const merged = {
446
- ...textBody,
447
- content: [...textBody.content, ...toolBody.content],
448
- stop_reason: bedrockStopReason(overrides?.finishReason, "tool_use")
449
- };
450
- res.writeHead(200, { "Content-Type": "application/json" });
451
- res.end(JSON.stringify(merged));
477
+ await require_deliver.deliverJson(res, journalEntry, fixture, () => {
478
+ const textBody = buildBedrockTextResponse(response.content ?? "", completionReq.model, effReasoning, overrides);
479
+ const toolBody = buildBedrockToolCallResponse(functionToolCalls, completionReq.model, logger, void 0, overrides);
480
+ return {
481
+ ...textBody,
482
+ content: [...textBody.content, ...toolBody.content],
483
+ stop_reason: bedrockStopReason(overrides?.finishReason, "tool_use")
484
+ };
485
+ }, jsonOpts(require_timing.servedPayloadLength(response, effReasoning)));
452
486
  return;
453
487
  }
454
488
  if (require_helpers.isTextResponse(response)) {
455
489
  if (response.webSearches?.length) logger.warn("webSearches in fixture response are not supported for Bedrock API — ignoring");
456
490
  const overrides = require_helpers.extractOverrides(response);
457
491
  const effReasoning = require_helpers.resolveReasoningForModel(response.reasoning, completionReq.model, require_policy.resolveRequestDecisions(defaults.strict, req.headers).reasoningSuppression, logger);
458
- addResponseEntry({
492
+ await require_deliver.deliverJson(res, addResponseEntry({
459
493
  method: req.method ?? "POST",
460
494
  path: urlPath,
461
495
  headers: require_helpers.flattenHeaders(req.headers),
@@ -464,17 +498,14 @@ async function handleBedrock(req, res, raw, modelId, fixtures, journal, defaults
464
498
  status: 200,
465
499
  fixture
466
500
  }
467
- });
468
- const body = buildBedrockTextResponse(response.content, completionReq.model, effReasoning, overrides);
469
- res.writeHead(200, { "Content-Type": "application/json" });
470
- res.end(JSON.stringify(body));
501
+ }), fixture, () => buildBedrockTextResponse(response.content, completionReq.model, effReasoning, overrides), jsonOpts(require_timing.servedPayloadLength(response, effReasoning)));
471
502
  return;
472
503
  }
473
504
  if (require_helpers.isToolCallResponse(response)) {
474
505
  if (response.webSearches?.length) logger.warn("webSearches in fixture response are not supported for Bedrock API — ignoring");
475
506
  const overrides = require_helpers.extractOverrides(response);
476
507
  const effReasoning = require_helpers.resolveReasoningForModel(response.reasoning, completionReq.model, require_policy.resolveRequestDecisions(defaults.strict, req.headers).reasoningSuppression, logger);
477
- addResponseEntry({
508
+ const journalEntry = addResponseEntry({
478
509
  method: req.method ?? "POST",
479
510
  path: urlPath,
480
511
  headers: require_helpers.flattenHeaders(req.headers),
@@ -484,9 +515,8 @@ async function handleBedrock(req, res, raw, modelId, fixtures, journal, defaults
484
515
  fixture
485
516
  }
486
517
  });
487
- const body = buildBedrockToolCallResponse(require_helpers.requireEmittedFunctionToolCalls(response, "Bedrock InvokeModel"), completionReq.model, logger, effReasoning, overrides);
488
- res.writeHead(200, { "Content-Type": "application/json" });
489
- res.end(JSON.stringify(body));
518
+ const functionToolCalls = require_helpers.requireEmittedFunctionToolCalls(response, "Bedrock InvokeModel");
519
+ await require_deliver.deliverJson(res, journalEntry, fixture, () => buildBedrockToolCallResponse(functionToolCalls, completionReq.model, logger, effReasoning, overrides), jsonOpts(require_timing.servedPayloadLength(response, effReasoning)));
490
520
  return;
491
521
  }
492
522
  addResponseEntry({
@@ -506,12 +536,7 @@ async function handleBedrock(req, res, raw, modelId, fixtures, journal, defaults
506
536
  }
507
537
  const BEDROCK_INVOKE_STREAM_EVENT_TYPE = "chunk";
508
538
  /** Serialize Claude events as InvokeModel PayloadPart, leaving generic AWS framing unchanged. */
509
- function writeBedrockInvokeStream(res, events, options) {
510
- return require_aws_event_stream.writeEventStream(res, events.map((event) => ({
511
- eventType: event.eventType,
512
- payload: { bytes: Buffer.from(JSON.stringify(event.payload), "utf8").toString("base64") }
513
- })), options);
514
- }
539
+ const bedrockInvokeCodec = require_aws_event_stream.eventStreamCodec((event) => require_aws_event_stream.encodeEventStreamMessage(event.eventType, { bytes: Buffer.from(JSON.stringify(event.payload), "utf8").toString("base64") }));
515
540
  function buildBedrockInvokeMessageStart(model, overrides) {
516
541
  return {
517
542
  eventType: BEDROCK_INVOKE_STREAM_EVENT_TYPE,
@@ -1010,7 +1035,10 @@ async function handleBedrockStream(req, res, raw, modelId, fixtures, journal, de
1010
1035
  completionReq._endpointType = "chat";
1011
1036
  completionReq._context = require_helpers.getContext(req);
1012
1037
  const testId = require_helpers.getTestId(req);
1013
- const { fixture, skippedBySequenceOrTurn } = require_router.matchFixtureDiagnostic(fixtures, completionReq, journal.getFixtureMatchCountsForTest(testId), defaults.requestTransform, require_router.recordMatchOptions(!!defaults.record, defaults.logger));
1038
+ const { fixture, skippedBySequenceOrTurn } = require_router.matchFixtureDiagnostic(fixtures, completionReq, journal.getFixtureMatchCountsForTest(testId), defaults.requestTransform, {
1039
+ ...require_router.recordMatchOptions(!!defaults.record, defaults.logger),
1040
+ wire: "bedrock-invoke"
1041
+ });
1014
1042
  if (fixture) logger.debug(`Fixture matched: ${JSON.stringify(fixture.match).slice(0, 120)}`);
1015
1043
  else logger.debug(`No fixture matched for request`);
1016
1044
  if (fixture) journal.incrementFixtureMatchCount(fixture, fixtures, testId);
@@ -1043,7 +1071,7 @@ async function handleBedrockStream(req, res, raw, modelId, fixtures, journal, de
1043
1071
  return;
1044
1072
  }
1045
1073
  if (defaults.record) {
1046
- const outcome = await require_recorder.proxyAndRecord(req, res, completionReq, "bedrock", urlPath, fixtures, defaults, raw);
1074
+ const { outcome, clientHungUp } = await require_proxy.withHangUpDetection(req, res, () => require_recorder.proxyAndRecord(req, res, completionReq, "bedrock", urlPath, fixtures, defaults, raw));
1047
1075
  if (outcome === "handled_by_hook") return;
1048
1076
  if (outcome !== "not_configured") {
1049
1077
  journal.add({
@@ -1054,7 +1082,8 @@ async function handleBedrockStream(req, res, raw, modelId, fixtures, journal, de
1054
1082
  response: {
1055
1083
  status: res.statusCode ?? 200,
1056
1084
  fixture: null,
1057
- source: "proxy"
1085
+ source: "proxy",
1086
+ ...require_proxy.proxyInterruption(res, clientHungUp)
1058
1087
  }
1059
1088
  });
1060
1089
  return;
@@ -1120,15 +1149,21 @@ async function handleBedrockStream(req, res, raw, modelId, fixtures, journal, de
1120
1149
  require_sse_writer.writeErrorResponse(res, misbehavior.status, renderedError.body);
1121
1150
  return;
1122
1151
  }
1123
- const latency = fixture.latency ?? defaults.latency;
1124
1152
  const chunkSize = Math.max(1, fixture.chunkSize ?? defaults.chunkSize);
1153
+ const streamTiming = {
1154
+ latency: fixture.latency ?? defaults.latency,
1155
+ streamingProfile: fixture.streamingProfile,
1156
+ recordedTimings: fixture.recordedTimings,
1157
+ replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed
1158
+ };
1125
1159
  if (misbehavior.kind === "applied") {
1126
1160
  const prepared = require_messages.prepareClaudeMisbehavior(misbehavior, {
1127
1161
  request: completionReq,
1128
1162
  stream: true,
1129
1163
  chunkSize,
1130
1164
  logger,
1131
- strict: require_policy.resolveRequestDecisions(defaults.strict, req.headers).reasoningSuppression
1165
+ strict: require_policy.resolveRequestDecisions(defaults.strict, req.headers).reasoningSuppression,
1166
+ citations: false
1132
1167
  });
1133
1168
  if (!prepared.stream) throw new TypeError("InvokeModel stream requires Claude events");
1134
1169
  const entry = journal.add({
@@ -1147,27 +1182,27 @@ async function handleBedrockStream(req, res, raw, modelId, fixtures, journal, de
1147
1182
  defaults,
1148
1183
  testId
1149
1184
  });
1150
- const events = prepared.events.map((event) => ({
1185
+ await require_deliver.deliverStream(res, entry, fixture, bedrockInvokeCodec, prepared.events.map((event) => ({
1151
1186
  eventType: BEDROCK_INVOKE_STREAM_EVENT_TYPE,
1152
1187
  payload: event
1153
- }));
1154
- const interruption = require_interruption.createInterruptionSignal(fixture);
1155
- try {
1156
- if (!await writeBedrockInvokeStream(res, events, {
1157
- latency,
1158
- streamingProfile: fixture.streamingProfile,
1159
- recordedTimings: fixture.recordedTimings,
1160
- replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed,
1161
- signal: interruption?.signal,
1162
- onChunkSent: interruption?.tick
1163
- })) {
1164
- if (!res.writableEnded) res.destroy();
1165
- entry.response.interrupted = true;
1166
- entry.response.interruptReason = interruption?.reason();
1167
- }
1168
- } finally {
1169
- interruption?.cleanup();
1170
- }
1188
+ })), streamTiming);
1189
+ return;
1190
+ }
1191
+ if (require_helpers.isRawResponse(response)) {
1192
+ await require_raw.serveRawResponse({
1193
+ wire: "bedrock-invoke",
1194
+ stream: true,
1195
+ req,
1196
+ res,
1197
+ fixture,
1198
+ response,
1199
+ body: completionReq,
1200
+ journal,
1201
+ defaults,
1202
+ testId,
1203
+ misbehaviorSummary: misbehavior.summary,
1204
+ errorWire: "bedrock"
1205
+ });
1171
1206
  return;
1172
1207
  }
1173
1208
  if (require_helpers.isErrorResponse(response)) {
@@ -1200,28 +1235,14 @@ async function handleBedrockStream(req, res, raw, modelId, fixtures, journal, de
1200
1235
  }
1201
1236
  });
1202
1237
  const functionToolCalls = require_helpers.requireEmittedFunctionToolCalls(response, "Bedrock InvokeModel");
1203
- const events = buildBedrockStreamContentWithToolCallsEvents(response.content ?? "", functionToolCalls, completionReq.model, chunkSize, logger, effReasoning, overrides, response.blocks);
1204
- const interruption = require_interruption.createInterruptionSignal(fixture);
1205
- if (!await writeBedrockInvokeStream(res, events, {
1206
- latency,
1207
- streamingProfile: fixture.streamingProfile,
1208
- recordedTimings: fixture.recordedTimings,
1209
- replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed,
1210
- signal: interruption?.signal,
1211
- onChunkSent: interruption?.tick
1212
- })) {
1213
- if (!res.writableEnded) res.destroy();
1214
- journalEntry.response.interrupted = true;
1215
- journalEntry.response.interruptReason = interruption?.reason();
1216
- }
1217
- interruption?.cleanup();
1238
+ await require_deliver.deliverStream(res, journalEntry, fixture, bedrockInvokeCodec, buildBedrockStreamContentWithToolCallsEvents(response.content ?? "", functionToolCalls, completionReq.model, chunkSize, logger, effReasoning, overrides, response.blocks), streamTiming);
1218
1239
  return;
1219
1240
  }
1220
1241
  if (require_helpers.isTextResponse(response)) {
1221
1242
  if (response.webSearches?.length) logger.warn("webSearches in fixture response are not supported for Bedrock API — ignoring");
1222
1243
  const overrides = require_helpers.extractOverrides(response);
1223
1244
  const effReasoning = require_helpers.resolveReasoningForModel(response.reasoning, completionReq.model, require_policy.resolveRequestDecisions(defaults.strict, req.headers).reasoningSuppression, logger);
1224
- const journalEntry = addResponseEntry({
1245
+ await require_deliver.deliverStream(res, addResponseEntry({
1225
1246
  method: req.method ?? "POST",
1226
1247
  path: urlPath,
1227
1248
  headers: require_helpers.flattenHeaders(req.headers),
@@ -1230,29 +1251,14 @@ async function handleBedrockStream(req, res, raw, modelId, fixtures, journal, de
1230
1251
  status: 200,
1231
1252
  fixture
1232
1253
  }
1233
- });
1234
- const events = buildBedrockStreamTextEvents(response.content, completionReq.model, chunkSize, effReasoning, overrides);
1235
- const interruption = require_interruption.createInterruptionSignal(fixture);
1236
- if (!await writeBedrockInvokeStream(res, events, {
1237
- latency,
1238
- streamingProfile: fixture.streamingProfile,
1239
- recordedTimings: fixture.recordedTimings,
1240
- replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed,
1241
- signal: interruption?.signal,
1242
- onChunkSent: interruption?.tick
1243
- })) {
1244
- if (!res.writableEnded) res.destroy();
1245
- journalEntry.response.interrupted = true;
1246
- journalEntry.response.interruptReason = interruption?.reason();
1247
- }
1248
- interruption?.cleanup();
1254
+ }), fixture, bedrockInvokeCodec, buildBedrockStreamTextEvents(response.content, completionReq.model, chunkSize, effReasoning, overrides), streamTiming);
1249
1255
  return;
1250
1256
  }
1251
1257
  if (require_helpers.isToolCallResponse(response)) {
1252
1258
  if (response.webSearches?.length) logger.warn("webSearches in fixture response are not supported for Bedrock API — ignoring");
1253
1259
  const overrides = require_helpers.extractOverrides(response);
1254
1260
  const effReasoning = require_helpers.resolveReasoningForModel(response.reasoning, completionReq.model, require_policy.resolveRequestDecisions(defaults.strict, req.headers).reasoningSuppression, logger);
1255
- const journalEntry = addResponseEntry({
1261
+ await require_deliver.deliverStream(res, addResponseEntry({
1256
1262
  method: req.method ?? "POST",
1257
1263
  path: urlPath,
1258
1264
  headers: require_helpers.flattenHeaders(req.headers),
@@ -1261,22 +1267,7 @@ async function handleBedrockStream(req, res, raw, modelId, fixtures, journal, de
1261
1267
  status: 200,
1262
1268
  fixture
1263
1269
  }
1264
- });
1265
- const events = buildBedrockStreamToolCallEvents(require_helpers.requireEmittedFunctionToolCalls(response, "Bedrock InvokeModel"), completionReq.model, chunkSize, logger, effReasoning, overrides);
1266
- const interruption = require_interruption.createInterruptionSignal(fixture);
1267
- if (!await writeBedrockInvokeStream(res, events, {
1268
- latency,
1269
- streamingProfile: fixture.streamingProfile,
1270
- recordedTimings: fixture.recordedTimings,
1271
- replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed,
1272
- signal: interruption?.signal,
1273
- onChunkSent: interruption?.tick
1274
- })) {
1275
- if (!res.writableEnded) res.destroy();
1276
- journalEntry.response.interrupted = true;
1277
- journalEntry.response.interruptReason = interruption?.reason();
1278
- }
1279
- interruption?.cleanup();
1270
+ }), fixture, bedrockInvokeCodec, buildBedrockStreamToolCallEvents(require_helpers.requireEmittedFunctionToolCalls(response, "Bedrock InvokeModel"), completionReq.model, chunkSize, logger, effReasoning, overrides), streamTiming);
1280
1271
  return;
1281
1272
  }
1282
1273
  addResponseEntry({