@copilotkit/aimock 1.22.0 → 1.22.1
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.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +15 -0
- package/dist/agui-types.d.cts.map +1 -1
- package/dist/agui-types.d.ts.map +1 -1
- package/dist/aimock-cli.cjs +0 -0
- package/dist/aimock-cli.js +0 -0
- package/dist/bedrock-converse.cjs +62 -22
- package/dist/bedrock-converse.cjs.map +1 -1
- package/dist/bedrock-converse.d.cts.map +1 -1
- package/dist/bedrock-converse.d.ts.map +1 -1
- package/dist/bedrock-converse.js +62 -22
- package/dist/bedrock-converse.js.map +1 -1
- package/dist/bedrock.cjs +59 -20
- package/dist/bedrock.cjs.map +1 -1
- package/dist/bedrock.d.cts.map +1 -1
- package/dist/bedrock.d.ts.map +1 -1
- package/dist/bedrock.js +59 -20
- package/dist/bedrock.js.map +1 -1
- package/dist/cli.cjs +1 -1
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/cohere.cjs +29 -9
- package/dist/cohere.cjs.map +1 -1
- package/dist/cohere.d.cts.map +1 -1
- package/dist/cohere.d.ts.map +1 -1
- package/dist/cohere.js +30 -10
- package/dist/cohere.js.map +1 -1
- package/dist/config-loader.d.cts.map +1 -1
- package/dist/constants.cjs +8 -0
- package/dist/constants.cjs.map +1 -0
- package/dist/constants.d.cts +8 -0
- package/dist/constants.d.cts.map +1 -0
- package/dist/constants.d.ts +8 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +7 -0
- package/dist/constants.js.map +1 -0
- package/dist/elevenlabs-audio.cjs +41 -18
- package/dist/elevenlabs-audio.cjs.map +1 -1
- package/dist/elevenlabs-audio.d.cts.map +1 -1
- package/dist/elevenlabs-audio.d.ts.map +1 -1
- package/dist/elevenlabs-audio.js +42 -19
- package/dist/elevenlabs-audio.js.map +1 -1
- package/dist/embeddings.cjs +19 -17
- package/dist/embeddings.cjs.map +1 -1
- package/dist/embeddings.d.cts.map +1 -1
- package/dist/embeddings.d.ts.map +1 -1
- package/dist/embeddings.js +20 -18
- package/dist/embeddings.js.map +1 -1
- package/dist/fal-audio.cjs +128 -39
- package/dist/fal-audio.cjs.map +1 -1
- package/dist/fal-audio.d.cts.map +1 -1
- package/dist/fal-audio.d.ts.map +1 -1
- package/dist/fal-audio.js +129 -40
- package/dist/fal-audio.js.map +1 -1
- package/dist/fal.cjs +25 -8
- package/dist/fal.cjs.map +1 -1
- package/dist/fal.d.cts.map +1 -1
- package/dist/fal.d.ts.map +1 -1
- package/dist/fal.js +26 -9
- package/dist/fal.js.map +1 -1
- package/dist/fixture-loader.cjs +9 -1
- package/dist/fixture-loader.cjs.map +1 -1
- package/dist/fixture-loader.js +9 -1
- package/dist/fixture-loader.js.map +1 -1
- package/dist/gemini-interactions.cjs +29 -7
- package/dist/gemini-interactions.cjs.map +1 -1
- package/dist/gemini-interactions.js +28 -8
- package/dist/gemini-interactions.js.map +1 -1
- package/dist/gemini.cjs +45 -19
- package/dist/gemini.cjs.map +1 -1
- package/dist/gemini.d.cts.map +1 -1
- package/dist/gemini.d.ts.map +1 -1
- package/dist/gemini.js +45 -19
- package/dist/gemini.js.map +1 -1
- package/dist/helpers.cjs +51 -8
- package/dist/helpers.cjs.map +1 -1
- package/dist/helpers.d.cts +6 -0
- package/dist/helpers.d.cts.map +1 -1
- package/dist/helpers.d.ts +6 -0
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +51 -9
- package/dist/helpers.js.map +1 -1
- package/dist/images.cjs +26 -8
- package/dist/images.cjs.map +1 -1
- package/dist/images.d.cts.map +1 -1
- package/dist/images.d.ts.map +1 -1
- package/dist/images.js +27 -9
- package/dist/images.js.map +1 -1
- package/dist/index.cjs +2 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/journal.cjs +17 -7
- package/dist/journal.cjs.map +1 -1
- package/dist/journal.d.cts +2 -3
- package/dist/journal.d.cts.map +1 -1
- package/dist/journal.d.ts +2 -3
- package/dist/journal.d.ts.map +1 -1
- package/dist/journal.js +15 -4
- package/dist/journal.js.map +1 -1
- package/dist/messages.cjs +33 -12
- package/dist/messages.cjs.map +1 -1
- package/dist/messages.d.cts.map +1 -1
- package/dist/messages.d.ts.map +1 -1
- package/dist/messages.js +33 -12
- package/dist/messages.js.map +1 -1
- package/dist/ollama.cjs +59 -18
- package/dist/ollama.cjs.map +1 -1
- package/dist/ollama.d.cts.map +1 -1
- package/dist/ollama.d.ts.map +1 -1
- package/dist/ollama.js +60 -19
- package/dist/ollama.js.map +1 -1
- package/dist/recorder.cjs +11 -7
- package/dist/recorder.cjs.map +1 -1
- package/dist/recorder.d.cts.map +1 -1
- package/dist/recorder.d.ts.map +1 -1
- package/dist/recorder.js +11 -7
- package/dist/recorder.js.map +1 -1
- package/dist/responses.cjs +61 -52
- package/dist/responses.cjs.map +1 -1
- package/dist/responses.d.cts +1 -1
- package/dist/responses.d.cts.map +1 -1
- package/dist/responses.d.ts +1 -1
- package/dist/responses.d.ts.map +1 -1
- package/dist/responses.js +62 -53
- package/dist/responses.js.map +1 -1
- package/dist/server.cjs +63 -179
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +39 -155
- package/dist/server.js.map +1 -1
- package/dist/speech.cjs +26 -8
- package/dist/speech.cjs.map +1 -1
- package/dist/speech.d.cts.map +1 -1
- package/dist/speech.d.ts.map +1 -1
- package/dist/speech.js +27 -9
- package/dist/speech.js.map +1 -1
- package/dist/transcription.cjs +57 -19
- package/dist/transcription.cjs.map +1 -1
- package/dist/transcription.d.cts.map +1 -1
- package/dist/transcription.d.ts.map +1 -1
- package/dist/transcription.js +58 -20
- package/dist/transcription.js.map +1 -1
- package/dist/types.d.cts +2 -0
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/vector-types.d.ts.map +1 -1
- package/dist/video.cjs +50 -14
- package/dist/video.cjs.map +1 -1
- package/dist/video.d.cts +8 -1
- package/dist/video.d.cts.map +1 -1
- package/dist/video.d.ts +8 -1
- package/dist/video.d.ts.map +1 -1
- package/dist/video.js +51 -15
- package/dist/video.js.map +1 -1
- package/dist/ws-gemini-live.cjs +34 -27
- package/dist/ws-gemini-live.cjs.map +1 -1
- package/dist/ws-gemini-live.d.cts.map +1 -1
- package/dist/ws-gemini-live.d.ts.map +1 -1
- package/dist/ws-gemini-live.js +34 -27
- package/dist/ws-gemini-live.js.map +1 -1
- package/dist/ws-realtime.cjs +251 -12
- package/dist/ws-realtime.cjs.map +1 -1
- package/dist/ws-realtime.d.cts.map +1 -1
- package/dist/ws-realtime.d.ts.map +1 -1
- package/dist/ws-realtime.js +251 -12
- package/dist/ws-realtime.js.map +1 -1
- package/dist/ws-responses.cjs +48 -12
- package/dist/ws-responses.cjs.map +1 -1
- package/dist/ws-responses.d.cts.map +1 -1
- package/dist/ws-responses.d.ts.map +1 -1
- package/dist/ws-responses.js +49 -13
- package/dist/ws-responses.js.map +1 -1
- package/package.json +2 -2
package/dist/bedrock-converse.js
CHANGED
|
@@ -106,8 +106,10 @@ function buildBedrockStreamTextEvents(content, chunkSize, reasoning, overrides)
|
|
|
106
106
|
}
|
|
107
107
|
function buildBedrockStreamContentWithToolCallsEvents(content, toolCalls, chunkSize, logger, reasoning, overrides) {
|
|
108
108
|
const events = buildBedrockStreamTextEvents(content, chunkSize, reasoning, overrides);
|
|
109
|
-
events.
|
|
110
|
-
|
|
109
|
+
for (let i = events.length - 1; i >= 0; i--) {
|
|
110
|
+
const et = events[i].eventType;
|
|
111
|
+
if (et === "metadata" || et === "messageStop") events.splice(i, 1);
|
|
112
|
+
}
|
|
111
113
|
let blockIndex = reasoning ? 2 : 1;
|
|
112
114
|
for (const tc of toolCalls) {
|
|
113
115
|
const toolUseId = tc.id || generateToolUseId();
|
|
@@ -233,7 +235,7 @@ function converseToCompletionRequest(req, modelId, logger) {
|
|
|
233
235
|
const textContent = msg.content.filter((b) => b.text !== void 0 && b.text !== "").map((b) => b.text ?? "").join("");
|
|
234
236
|
if (toolUseBlocks.length > 0) messages.push({
|
|
235
237
|
role: "assistant",
|
|
236
|
-
content: textContent
|
|
238
|
+
content: textContent || null,
|
|
237
239
|
tool_calls: toolUseBlocks.map((b) => ({
|
|
238
240
|
id: b.toolUse.toolUseId,
|
|
239
241
|
type: "function",
|
|
@@ -245,7 +247,7 @@ function converseToCompletionRequest(req, modelId, logger) {
|
|
|
245
247
|
});
|
|
246
248
|
else messages.push({
|
|
247
249
|
role: "assistant",
|
|
248
|
-
content: textContent
|
|
250
|
+
content: textContent || null
|
|
249
251
|
});
|
|
250
252
|
} else {
|
|
251
253
|
const warnMsg = `Unexpected message role "${msg.role}" in Converse request — skipping`;
|
|
@@ -391,8 +393,31 @@ async function handleConverse(req, res, raw, modelId, fixtures, journal, default
|
|
|
391
393
|
body: completionReq
|
|
392
394
|
}, fixture ? "fixture" : "proxy", defaults.registry, defaults.logger)) return;
|
|
393
395
|
if (!fixture) {
|
|
396
|
+
if (resolveStrictMode(defaults.strict, req.headers)) {
|
|
397
|
+
const strictStatus = 503;
|
|
398
|
+
const strictMessage = "Strict mode: no fixture matched";
|
|
399
|
+
logger.error(`STRICT: No fixture matched for ${req.method ?? "POST"} ${urlPath}`);
|
|
400
|
+
journal.add({
|
|
401
|
+
method: req.method ?? "POST",
|
|
402
|
+
path: urlPath,
|
|
403
|
+
headers: flattenHeaders(req.headers),
|
|
404
|
+
body: completionReq,
|
|
405
|
+
response: {
|
|
406
|
+
status: strictStatus,
|
|
407
|
+
fixture: null,
|
|
408
|
+
...strictOverrideField(defaults.strict, req.headers)
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
writeErrorResponse(res, strictStatus, JSON.stringify({ error: {
|
|
412
|
+
message: strictMessage,
|
|
413
|
+
type: "invalid_request_error"
|
|
414
|
+
} }));
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
394
417
|
if (defaults.record) {
|
|
395
|
-
|
|
418
|
+
const outcome = await proxyAndRecord(req, res, completionReq, "bedrock", urlPath, fixtures, defaults, raw);
|
|
419
|
+
if (outcome === "handled_by_hook") return;
|
|
420
|
+
if (outcome !== "not_configured") {
|
|
396
421
|
journal.add({
|
|
397
422
|
method: req.method ?? "POST",
|
|
398
423
|
path: urlPath,
|
|
@@ -407,23 +432,19 @@ async function handleConverse(req, res, raw, modelId, fixtures, journal, default
|
|
|
407
432
|
return;
|
|
408
433
|
}
|
|
409
434
|
}
|
|
410
|
-
const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);
|
|
411
|
-
const strictStatus = effectiveStrict ? 503 : 404;
|
|
412
|
-
const strictMessage = effectiveStrict ? "Strict mode: no fixture matched" : "No fixture matched";
|
|
413
|
-
if (effectiveStrict) logger.error(`STRICT: No fixture matched for ${req.method ?? "POST"} ${urlPath}`);
|
|
414
435
|
journal.add({
|
|
415
436
|
method: req.method ?? "POST",
|
|
416
437
|
path: urlPath,
|
|
417
438
|
headers: flattenHeaders(req.headers),
|
|
418
439
|
body: completionReq,
|
|
419
440
|
response: {
|
|
420
|
-
status:
|
|
441
|
+
status: 404,
|
|
421
442
|
fixture: null,
|
|
422
443
|
...strictOverrideField(defaults.strict, req.headers)
|
|
423
444
|
}
|
|
424
445
|
});
|
|
425
|
-
writeErrorResponse(res,
|
|
426
|
-
message:
|
|
446
|
+
writeErrorResponse(res, 404, JSON.stringify({ error: {
|
|
447
|
+
message: "No fixture matched",
|
|
427
448
|
type: "invalid_request_error"
|
|
428
449
|
} }));
|
|
429
450
|
return;
|
|
@@ -488,7 +509,7 @@ async function handleConverse(req, res, raw, modelId, fixtures, journal, default
|
|
|
488
509
|
return;
|
|
489
510
|
}
|
|
490
511
|
if (isToolCallResponse(response)) {
|
|
491
|
-
if (
|
|
512
|
+
if (response.webSearches?.length) logger.warn("webSearches in fixture response are not supported for Bedrock Converse API — ignoring");
|
|
492
513
|
const overrides = extractOverrides(response);
|
|
493
514
|
journal.add({
|
|
494
515
|
method: req.method ?? "POST",
|
|
@@ -577,8 +598,31 @@ async function handleConverseStream(req, res, raw, modelId, fixtures, journal, d
|
|
|
577
598
|
body: completionReq
|
|
578
599
|
}, fixture ? "fixture" : "proxy", defaults.registry, defaults.logger)) return;
|
|
579
600
|
if (!fixture) {
|
|
601
|
+
if (resolveStrictMode(defaults.strict, req.headers)) {
|
|
602
|
+
const strictStatus = 503;
|
|
603
|
+
const strictMessage = "Strict mode: no fixture matched";
|
|
604
|
+
logger.error(`STRICT: No fixture matched for ${req.method ?? "POST"} ${urlPath}`);
|
|
605
|
+
journal.add({
|
|
606
|
+
method: req.method ?? "POST",
|
|
607
|
+
path: urlPath,
|
|
608
|
+
headers: flattenHeaders(req.headers),
|
|
609
|
+
body: completionReq,
|
|
610
|
+
response: {
|
|
611
|
+
status: strictStatus,
|
|
612
|
+
fixture: null,
|
|
613
|
+
...strictOverrideField(defaults.strict, req.headers)
|
|
614
|
+
}
|
|
615
|
+
});
|
|
616
|
+
writeErrorResponse(res, strictStatus, JSON.stringify({ error: {
|
|
617
|
+
message: strictMessage,
|
|
618
|
+
type: "invalid_request_error"
|
|
619
|
+
} }));
|
|
620
|
+
return;
|
|
621
|
+
}
|
|
580
622
|
if (defaults.record) {
|
|
581
|
-
|
|
623
|
+
const outcome = await proxyAndRecord(req, res, completionReq, "bedrock", urlPath, fixtures, defaults, raw);
|
|
624
|
+
if (outcome === "handled_by_hook") return;
|
|
625
|
+
if (outcome !== "not_configured") {
|
|
582
626
|
journal.add({
|
|
583
627
|
method: req.method ?? "POST",
|
|
584
628
|
path: urlPath,
|
|
@@ -593,23 +637,19 @@ async function handleConverseStream(req, res, raw, modelId, fixtures, journal, d
|
|
|
593
637
|
return;
|
|
594
638
|
}
|
|
595
639
|
}
|
|
596
|
-
const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);
|
|
597
|
-
const strictStatus = effectiveStrict ? 503 : 404;
|
|
598
|
-
const strictMessage = effectiveStrict ? "Strict mode: no fixture matched" : "No fixture matched";
|
|
599
|
-
if (effectiveStrict) logger.error(`STRICT: No fixture matched for ${req.method ?? "POST"} ${urlPath}`);
|
|
600
640
|
journal.add({
|
|
601
641
|
method: req.method ?? "POST",
|
|
602
642
|
path: urlPath,
|
|
603
643
|
headers: flattenHeaders(req.headers),
|
|
604
644
|
body: completionReq,
|
|
605
645
|
response: {
|
|
606
|
-
status:
|
|
646
|
+
status: 404,
|
|
607
647
|
fixture: null,
|
|
608
648
|
...strictOverrideField(defaults.strict, req.headers)
|
|
609
649
|
}
|
|
610
650
|
});
|
|
611
|
-
writeErrorResponse(res,
|
|
612
|
-
message:
|
|
651
|
+
writeErrorResponse(res, 404, JSON.stringify({ error: {
|
|
652
|
+
message: "No fixture matched",
|
|
613
653
|
type: "invalid_request_error"
|
|
614
654
|
} }));
|
|
615
655
|
return;
|
|
@@ -696,7 +736,7 @@ async function handleConverseStream(req, res, raw, modelId, fixtures, journal, d
|
|
|
696
736
|
return;
|
|
697
737
|
}
|
|
698
738
|
if (isToolCallResponse(response)) {
|
|
699
|
-
if (
|
|
739
|
+
if (response.webSearches?.length) logger.warn("webSearches in fixture response are not supported for Bedrock Converse API — ignoring");
|
|
700
740
|
const overrides = extractOverrides(response);
|
|
701
741
|
const journalEntry = journal.add({
|
|
702
742
|
method: req.method ?? "POST",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bedrock-converse.js","names":[],"sources":["../src/bedrock-converse.ts"],"sourcesContent":["/**\n * AWS Bedrock Converse API support.\n *\n * Translates incoming Converse and Converse-stream requests (Bedrock Converse\n * format) into the ChatCompletionRequest format used by the fixture router,\n * and converts fixture responses back into Converse API format — either a\n * single JSON response or an Event Stream binary stream.\n */\n\nimport type * as http from \"node:http\";\nimport type {\n ChatCompletionRequest,\n ChatMessage,\n Fixture,\n HandlerDefaults,\n ResponseOverrides,\n ToolCall,\n ToolDefinition,\n} from \"./types.js\";\nimport {\n generateToolUseId,\n extractOverrides,\n isTextResponse,\n isToolCallResponse,\n isContentWithToolCallsResponse,\n isErrorResponse,\n flattenHeaders,\n getTestId,\n resolveResponse,\n resolveStrictMode,\n strictOverrideField,\n} from \"./helpers.js\";\nimport { matchFixture } from \"./router.js\";\nimport { writeErrorResponse } from \"./sse-writer.js\";\nimport { writeEventStream } from \"./aws-event-stream.js\";\nimport { createInterruptionSignal } from \"./interruption.js\";\nimport type { Journal } from \"./journal.js\";\nimport type { Logger } from \"./logger.js\";\nimport { applyChaos } from \"./chaos.js\";\nimport { proxyAndRecord } from \"./recorder.js\";\n\n// ─── Converse request types ─────────────────────────────────────────────────\n\ninterface ConverseContentBlock {\n text?: string;\n toolUse?: { toolUseId: string; name: string; input: object };\n toolResult?: { toolUseId: string; content: { text?: string }[] };\n}\n\ninterface ConverseMessage {\n role: \"user\" | \"assistant\";\n content: ConverseContentBlock[];\n}\n\ninterface ConverseToolSpec {\n name: string;\n description?: string;\n inputSchema?: object;\n}\n\ninterface ConverseRequest {\n messages: ConverseMessage[];\n system?: { text: string }[];\n inferenceConfig?: { maxTokens?: number; temperature?: number };\n toolConfig?: { tools: { toolSpec: ConverseToolSpec }[] };\n}\n\n// ─── Converse stop_reason mapping ──────────────────────────────────────────\n\nfunction converseStopReason(\n overrideFinishReason: string | undefined,\n defaultReason: string,\n): string {\n if (!overrideFinishReason) return defaultReason;\n if (overrideFinishReason === \"stop\") return \"end_turn\";\n if (overrideFinishReason === \"tool_calls\") return \"tool_use\";\n if (overrideFinishReason === \"length\") return \"max_tokens\";\n return overrideFinishReason;\n}\n\n/**\n * Build Converse-format usage from fixture overrides.\n *\n * When no overrides are provided (the common case for mocks), all token\n * counts default to zero. This is intentional — aimock is a mock server\n * and does not perform real tokenisation. Callers that need non-zero\n * usage should supply explicit `usage` overrides in their fixture.\n */\nfunction converseUsage(overrides?: ResponseOverrides): {\n inputTokens: number;\n outputTokens: number;\n totalTokens: number;\n} {\n if (!overrides?.usage) return { inputTokens: 0, outputTokens: 0, totalTokens: 0 };\n const inputTokens = overrides.usage.input_tokens ?? overrides.usage.prompt_tokens ?? 0;\n const outputTokens = overrides.usage.output_tokens ?? overrides.usage.completion_tokens ?? 0;\n return { inputTokens, outputTokens, totalTokens: inputTokens + outputTokens };\n}\n\nfunction parseConverseToolArgumentsForStream(toolCall: ToolCall, logger: Logger): string {\n try {\n const parsed = JSON.parse(toolCall.arguments || \"{}\");\n return JSON.stringify(parsed);\n } catch {\n logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${toolCall.name}\": ${toolCall.arguments}`,\n );\n return \"{}\";\n }\n}\n\nfunction buildBedrockStreamTextEvents(\n content: string,\n chunkSize: number,\n reasoning?: string,\n overrides?: ResponseOverrides,\n): Array<{ eventType: string; payload: object }> {\n const events: Array<{ eventType: string; payload: object }> = [\n { eventType: \"messageStart\", payload: { role: \"assistant\" } },\n ];\n\n if (reasoning) {\n const blockIndex = 0;\n events.push({\n eventType: \"contentBlockStart\",\n payload: { contentBlockIndex: blockIndex, start: { reasoningContent: {} } },\n });\n for (let i = 0; i < reasoning.length; i += chunkSize) {\n events.push({\n eventType: \"contentBlockDelta\",\n payload: {\n contentBlockIndex: blockIndex,\n delta: { reasoningContent: { text: reasoning.slice(i, i + chunkSize) } },\n },\n });\n }\n events.push({\n eventType: \"contentBlockStop\",\n payload: { contentBlockIndex: blockIndex },\n });\n }\n\n const textBlockIndex = reasoning ? 1 : 0;\n events.push({\n eventType: \"contentBlockStart\",\n payload: { contentBlockIndex: textBlockIndex, start: {} },\n });\n for (let i = 0; i < content.length; i += chunkSize) {\n events.push({\n eventType: \"contentBlockDelta\",\n payload: {\n contentBlockIndex: textBlockIndex,\n delta: { text: content.slice(i, i + chunkSize) },\n },\n });\n }\n events.push({\n eventType: \"contentBlockStop\",\n payload: { contentBlockIndex: textBlockIndex },\n });\n events.push({\n eventType: \"messageStop\",\n payload: { stopReason: converseStopReason(overrides?.finishReason, \"end_turn\") },\n });\n const usage = converseUsage(overrides);\n events.push({\n eventType: \"metadata\",\n payload: { usage, metrics: { latencyMs: 0 } },\n });\n return events;\n}\n\nfunction buildBedrockStreamContentWithToolCallsEvents(\n content: string,\n toolCalls: ToolCall[],\n chunkSize: number,\n logger: Logger,\n reasoning?: string,\n overrides?: ResponseOverrides,\n): Array<{ eventType: string; payload: object }> {\n const events = buildBedrockStreamTextEvents(content, chunkSize, reasoning, overrides);\n // Remove trailing metadata + messageStop events — we re-emit them after tool blocks\n events.pop(); // metadata\n events.pop(); // messageStop\n let blockIndex = reasoning ? 2 : 1;\n\n for (const tc of toolCalls) {\n const toolUseId = tc.id || generateToolUseId();\n events.push({\n eventType: \"contentBlockStart\",\n payload: {\n contentBlockIndex: blockIndex,\n start: { toolUse: { toolUseId, name: tc.name } },\n },\n });\n const argsStr = parseConverseToolArgumentsForStream(tc, logger);\n for (let i = 0; i < argsStr.length; i += chunkSize) {\n events.push({\n eventType: \"contentBlockDelta\",\n payload: {\n contentBlockIndex: blockIndex,\n delta: { toolUse: { input: argsStr.slice(i, i + chunkSize) } },\n },\n });\n }\n events.push({\n eventType: \"contentBlockStop\",\n payload: { contentBlockIndex: blockIndex },\n });\n blockIndex++;\n }\n events.push({\n eventType: \"messageStop\",\n payload: { stopReason: converseStopReason(overrides?.finishReason, \"tool_use\") },\n });\n const usage = converseUsage(overrides);\n events.push({\n eventType: \"metadata\",\n payload: { usage, metrics: { latencyMs: 0 } },\n });\n return events;\n}\n\nfunction buildBedrockStreamToolCallEvents(\n toolCalls: ToolCall[],\n chunkSize: number,\n logger: Logger,\n overrides?: ResponseOverrides,\n): Array<{ eventType: string; payload: object }> {\n const events: Array<{ eventType: string; payload: object }> = [\n { eventType: \"messageStart\", payload: { role: \"assistant\" } },\n ];\n\n for (let tcIdx = 0; tcIdx < toolCalls.length; tcIdx++) {\n const tc = toolCalls[tcIdx];\n const toolUseId = tc.id || generateToolUseId();\n events.push({\n eventType: \"contentBlockStart\",\n payload: {\n contentBlockIndex: tcIdx,\n start: { toolUse: { toolUseId, name: tc.name } },\n },\n });\n const argsStr = parseConverseToolArgumentsForStream(tc, logger);\n for (let i = 0; i < argsStr.length; i += chunkSize) {\n events.push({\n eventType: \"contentBlockDelta\",\n payload: {\n contentBlockIndex: tcIdx,\n delta: { toolUse: { input: argsStr.slice(i, i + chunkSize) } },\n },\n });\n }\n events.push({\n eventType: \"contentBlockStop\",\n payload: { contentBlockIndex: tcIdx },\n });\n }\n events.push({\n eventType: \"messageStop\",\n payload: { stopReason: converseStopReason(overrides?.finishReason, \"tool_use\") },\n });\n const usage = converseUsage(overrides);\n events.push({\n eventType: \"metadata\",\n payload: { usage, metrics: { latencyMs: 0 } },\n });\n return events;\n}\n\n// ─── Input conversion: Converse → ChatCompletionRequest ─────────────────────\n\nexport function converseToCompletionRequest(\n req: ConverseRequest,\n modelId: string,\n logger?: Logger,\n): ChatCompletionRequest {\n const messages: ChatMessage[] = [];\n\n // system field → system message\n if (req.system && req.system.length > 0) {\n const systemText = req.system.map((s) => s.text).join(\"\");\n if (systemText) {\n messages.push({ role: \"system\", content: systemText });\n }\n }\n\n for (const msg of req.messages) {\n if (msg.role === \"user\") {\n // Check for toolResult blocks\n const toolResults = msg.content.filter((b) => b.toolResult);\n const textBlocks = msg.content.filter(\n (b) => b.text !== undefined && b.text !== \"\" && !b.toolResult,\n );\n const unsupportedBlocks = msg.content.filter(\n (b) => b.text === undefined && !b.toolResult && !b.toolUse,\n );\n if (unsupportedBlocks.length > 0 && logger) {\n logger.warn(\n `Converse user message contains unsupported content block types — these will be dropped during conversion`,\n );\n }\n\n if (toolResults.length > 0) {\n for (const block of toolResults) {\n const tr = block.toolResult!;\n const resultContent = tr.content.map((c) => c.text ?? \"\").join(\"\");\n messages.push({\n role: \"tool\",\n content: resultContent,\n tool_call_id: tr.toolUseId,\n });\n }\n if (textBlocks.length > 0) {\n messages.push({\n role: \"user\",\n content: textBlocks.map((b) => b.text ?? \"\").join(\"\"),\n });\n }\n continue;\n }\n\n // Plain user message\n const text = msg.content\n .filter((b) => b.text !== undefined && b.text !== \"\")\n .map((b) => b.text ?? \"\")\n .join(\"\");\n messages.push({ role: \"user\", content: text });\n } else if (msg.role === \"assistant\") {\n const toolUseBlocks = msg.content.filter((b) => b.toolUse);\n const textContent = msg.content\n .filter((b) => b.text !== undefined && b.text !== \"\")\n .map((b) => b.text ?? \"\")\n .join(\"\");\n\n if (toolUseBlocks.length > 0) {\n messages.push({\n role: \"assistant\",\n content: textContent ?? null,\n tool_calls: toolUseBlocks.map((b) => ({\n id: b.toolUse!.toolUseId,\n type: \"function\" as const,\n function: {\n name: b.toolUse!.name,\n arguments: JSON.stringify(b.toolUse!.input),\n },\n })),\n });\n } else {\n messages.push({ role: \"assistant\", content: textContent ?? null });\n }\n } else {\n const warnMsg = `Unexpected message role \"${msg.role}\" in Converse request — skipping`;\n if (logger) {\n logger.warn(warnMsg);\n }\n }\n }\n\n // Convert tools\n let tools: ToolDefinition[] | undefined;\n if (req.toolConfig?.tools && req.toolConfig.tools.length > 0) {\n tools = req.toolConfig.tools.map((t) => ({\n type: \"function\" as const,\n function: {\n name: t.toolSpec.name,\n description: t.toolSpec.description,\n parameters: (t.toolSpec.inputSchema && \"json\" in t.toolSpec.inputSchema\n ? (t.toolSpec.inputSchema as Record<string, unknown>).json\n : t.toolSpec.inputSchema) as object | undefined,\n },\n }));\n }\n\n return {\n model: modelId,\n messages,\n stream: false,\n temperature: req.inferenceConfig?.temperature,\n max_tokens: req.inferenceConfig?.maxTokens,\n tools,\n };\n}\n\n// ─── Response builders ──────────────────────────────────────────────────────\n\nfunction buildConverseTextResponse(\n content: string,\n reasoning?: string,\n overrides?: ResponseOverrides,\n): object {\n const contentBlocks: object[] = [];\n if (reasoning) {\n contentBlocks.push({\n reasoningContent: { reasoningText: { text: reasoning } },\n });\n }\n contentBlocks.push({ text: content });\n\n return {\n output: {\n message: {\n role: \"assistant\",\n content: contentBlocks,\n },\n },\n stopReason: converseStopReason(overrides?.finishReason, \"end_turn\"),\n usage: converseUsage(overrides),\n metrics: { latencyMs: 0 },\n };\n}\n\nfunction buildConverseToolCallResponse(\n toolCalls: ToolCall[],\n logger: Logger,\n overrides?: ResponseOverrides,\n): object {\n return {\n output: {\n message: {\n role: \"assistant\",\n content: toolCalls.map((tc) => {\n let argsObj: unknown;\n try {\n argsObj = JSON.parse(tc.arguments || \"{}\");\n } catch {\n logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n );\n argsObj = {};\n }\n return {\n toolUse: {\n toolUseId: tc.id || generateToolUseId(),\n name: tc.name,\n input: argsObj,\n },\n };\n }),\n },\n },\n stopReason: converseStopReason(overrides?.finishReason, \"tool_use\"),\n usage: converseUsage(overrides),\n metrics: { latencyMs: 0 },\n };\n}\n\nfunction buildConverseContentWithToolCallsResponse(\n content: string,\n toolCalls: ToolCall[],\n logger: Logger,\n reasoning?: string,\n overrides?: ResponseOverrides,\n): object {\n const contentBlocks: object[] = [];\n if (reasoning) {\n contentBlocks.push({\n reasoningContent: { reasoningText: { text: reasoning } },\n });\n }\n contentBlocks.push({ text: content });\n for (const tc of toolCalls) {\n let argsObj: unknown;\n try {\n argsObj = JSON.parse(tc.arguments || \"{}\");\n } catch {\n logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n );\n argsObj = {};\n }\n contentBlocks.push({\n toolUse: {\n toolUseId: tc.id || generateToolUseId(),\n name: tc.name,\n input: argsObj,\n },\n });\n }\n\n return {\n output: {\n message: {\n role: \"assistant\",\n content: contentBlocks,\n },\n },\n stopReason: converseStopReason(overrides?.finishReason, \"tool_use\"),\n usage: converseUsage(overrides),\n metrics: { latencyMs: 0 },\n };\n}\n\n// ─── Request handlers ───────────────────────────────────────────────────────\n\nexport async function handleConverse(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n raw: string,\n modelId: string,\n fixtures: Fixture[],\n journal: Journal,\n defaults: HandlerDefaults,\n setCorsHeaders: (res: http.ServerResponse) => void,\n): Promise<void> {\n const { logger } = defaults;\n setCorsHeaders(res);\n\n const urlPath = req.url ?? `/model/${modelId}/converse`;\n\n let converseReq: ConverseRequest;\n try {\n converseReq = JSON.parse(raw) as ConverseRequest;\n } catch (parseErr) {\n const detail = parseErr instanceof Error ? parseErr.message : \"unknown\";\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: {\n message: `Malformed JSON: ${detail}`,\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n if (!converseReq.messages || !Array.isArray(converseReq.messages)) {\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: {\n message: \"Invalid request: messages array is required\",\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n const completionReq = converseToCompletionRequest(converseReq, modelId, logger);\n completionReq._endpointType = \"chat\";\n\n const testId = getTestId(req);\n const fixture = matchFixture(\n fixtures,\n completionReq,\n journal.getFixtureMatchCountsForTest(testId),\n defaults.requestTransform,\n );\n\n if (fixture) {\n logger.debug(`Fixture matched: ${JSON.stringify(fixture.match).slice(0, 120)}`);\n } else {\n logger.debug(`No fixture matched for request`);\n }\n\n if (fixture) {\n journal.incrementFixtureMatchCount(fixture, fixtures, testId);\n }\n\n if (\n applyChaos(\n res,\n fixture,\n defaults.chaos,\n req.headers,\n journal,\n {\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n },\n fixture ? \"fixture\" : \"proxy\",\n defaults.registry,\n defaults.logger,\n )\n )\n return;\n\n if (!fixture) {\n if (defaults.record) {\n const outcome = await proxyAndRecord(\n req,\n res,\n completionReq,\n \"bedrock\",\n urlPath,\n fixtures,\n defaults,\n raw,\n );\n if (outcome !== \"not_configured\") {\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: res.statusCode ?? 200, fixture: null, source: \"proxy\" },\n });\n return;\n }\n }\n const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);\n const strictStatus = effectiveStrict ? 503 : 404;\n const strictMessage = effectiveStrict\n ? \"Strict mode: no fixture matched\"\n : \"No fixture matched\";\n if (effectiveStrict) {\n logger.error(`STRICT: No fixture matched for ${req.method ?? \"POST\"} ${urlPath}`);\n }\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: {\n status: strictStatus,\n fixture: null,\n ...strictOverrideField(defaults.strict, req.headers),\n },\n });\n writeErrorResponse(\n res,\n strictStatus,\n JSON.stringify({\n error: {\n message: strictMessage,\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n const response = await resolveResponse(fixture, completionReq);\n\n // Error response\n if (isErrorResponse(response)) {\n const status = response.status ?? 500;\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status, fixture },\n });\n const errBody = {\n type: \"error\",\n error: {\n type: response.error.type ?? \"invalid_request_error\",\n message: response.error.message,\n },\n };\n writeErrorResponse(res, status, JSON.stringify(errBody));\n return;\n }\n\n // Content + tool calls response\n if (isContentWithToolCallsResponse(response)) {\n if (response.webSearches?.length) {\n logger.warn(\n \"webSearches in fixture response are not supported for Bedrock Converse API — ignoring\",\n );\n }\n const overrides = extractOverrides(response);\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n const body = buildConverseContentWithToolCallsResponse(\n response.content,\n response.toolCalls,\n logger,\n response.reasoning,\n overrides,\n );\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n return;\n }\n\n // Text response\n if (isTextResponse(response)) {\n if (response.webSearches?.length) {\n logger.warn(\n \"webSearches in fixture response are not supported for Bedrock Converse API — ignoring\",\n );\n }\n const overrides = extractOverrides(response);\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n const body = buildConverseTextResponse(response.content, response.reasoning, overrides);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n return;\n }\n\n // Tool call response\n if (isToolCallResponse(response)) {\n if (\"webSearches\" in response) {\n logger.warn(\n \"webSearches in fixture response are not supported for Bedrock Converse API — ignoring\",\n );\n }\n const overrides = extractOverrides(response);\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n const body = buildConverseToolCallResponse(response.toolCalls, logger, overrides);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n return;\n }\n\n // Unknown response type\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 500, fixture },\n });\n writeErrorResponse(\n res,\n 500,\n JSON.stringify({\n error: {\n message: \"Fixture response did not match any known type\",\n type: \"server_error\",\n },\n }),\n );\n}\n\nexport async function handleConverseStream(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n raw: string,\n modelId: string,\n fixtures: Fixture[],\n journal: Journal,\n defaults: HandlerDefaults,\n setCorsHeaders: (res: http.ServerResponse) => void,\n): Promise<void> {\n const { logger } = defaults;\n setCorsHeaders(res);\n\n const urlPath = req.url ?? `/model/${modelId}/converse-stream`;\n\n let converseReq: ConverseRequest;\n try {\n converseReq = JSON.parse(raw) as ConverseRequest;\n } catch (parseErr) {\n const detail = parseErr instanceof Error ? parseErr.message : \"unknown\";\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: {\n message: `Malformed JSON: ${detail}`,\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n if (!converseReq.messages || !Array.isArray(converseReq.messages)) {\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: {\n message: \"Invalid request: messages array is required\",\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n const completionReq = converseToCompletionRequest(converseReq, modelId, logger);\n completionReq.stream = true;\n completionReq._endpointType = \"chat\";\n\n const testId = getTestId(req);\n const fixture = matchFixture(\n fixtures,\n completionReq,\n journal.getFixtureMatchCountsForTest(testId),\n defaults.requestTransform,\n );\n\n if (fixture) {\n logger.debug(`Fixture matched: ${JSON.stringify(fixture.match).slice(0, 120)}`);\n } else {\n logger.debug(`No fixture matched for request`);\n }\n\n if (fixture) {\n journal.incrementFixtureMatchCount(fixture, fixtures, testId);\n }\n\n if (\n applyChaos(\n res,\n fixture,\n defaults.chaos,\n req.headers,\n journal,\n {\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n },\n fixture ? \"fixture\" : \"proxy\",\n defaults.registry,\n defaults.logger,\n )\n )\n return;\n\n if (!fixture) {\n if (defaults.record) {\n const outcome = await proxyAndRecord(\n req,\n res,\n completionReq,\n \"bedrock\",\n urlPath,\n fixtures,\n defaults,\n raw,\n );\n if (outcome !== \"not_configured\") {\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: res.statusCode ?? 200, fixture: null, source: \"proxy\" },\n });\n return;\n }\n }\n const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);\n const strictStatus = effectiveStrict ? 503 : 404;\n const strictMessage = effectiveStrict\n ? \"Strict mode: no fixture matched\"\n : \"No fixture matched\";\n if (effectiveStrict) {\n logger.error(`STRICT: No fixture matched for ${req.method ?? \"POST\"} ${urlPath}`);\n }\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: {\n status: strictStatus,\n fixture: null,\n ...strictOverrideField(defaults.strict, req.headers),\n },\n });\n writeErrorResponse(\n res,\n strictStatus,\n JSON.stringify({\n error: {\n message: strictMessage,\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n const response = await resolveResponse(fixture, completionReq);\n const latency = fixture.latency ?? defaults.latency;\n const chunkSize = Math.max(1, fixture.chunkSize ?? defaults.chunkSize);\n\n // Error response\n if (isErrorResponse(response)) {\n const status = response.status ?? 500;\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status, fixture },\n });\n const errBody = {\n type: \"error\",\n error: {\n type: response.error.type ?? \"invalid_request_error\",\n message: response.error.message,\n },\n };\n writeErrorResponse(res, status, JSON.stringify(errBody));\n return;\n }\n\n // Content + tool calls response — stream as Event Stream\n if (isContentWithToolCallsResponse(response)) {\n if (response.webSearches?.length) {\n logger.warn(\n \"webSearches in fixture response are not supported for Bedrock Converse API — ignoring\",\n );\n }\n const overrides = extractOverrides(response);\n const journalEntry = journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n const events = buildBedrockStreamContentWithToolCallsEvents(\n response.content,\n response.toolCalls,\n chunkSize,\n logger,\n response.reasoning,\n overrides,\n );\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeEventStream(res, events, {\n latency,\n streamingProfile: fixture.streamingProfile,\n signal: interruption?.signal,\n onChunkSent: interruption?.tick,\n });\n if (!completed) {\n if (!res.writableEnded) res.destroy();\n journalEntry.response.interrupted = true;\n journalEntry.response.interruptReason = interruption?.reason();\n }\n interruption?.cleanup();\n return;\n }\n\n // Text response — stream as Event Stream\n if (isTextResponse(response)) {\n if (response.webSearches?.length) {\n logger.warn(\n \"webSearches in fixture response are not supported for Bedrock Converse API — ignoring\",\n );\n }\n const overrides = extractOverrides(response);\n const journalEntry = journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n const events = buildBedrockStreamTextEvents(\n response.content,\n chunkSize,\n response.reasoning,\n overrides,\n );\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeEventStream(res, events, {\n latency,\n streamingProfile: fixture.streamingProfile,\n signal: interruption?.signal,\n onChunkSent: interruption?.tick,\n });\n if (!completed) {\n if (!res.writableEnded) res.destroy();\n journalEntry.response.interrupted = true;\n journalEntry.response.interruptReason = interruption?.reason();\n }\n interruption?.cleanup();\n return;\n }\n\n // Tool call response — stream as Event Stream\n if (isToolCallResponse(response)) {\n if (\"webSearches\" in response) {\n logger.warn(\n \"webSearches in fixture response are not supported for Bedrock Converse API — ignoring\",\n );\n }\n const overrides = extractOverrides(response);\n const journalEntry = journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n const events = buildBedrockStreamToolCallEvents(\n response.toolCalls,\n chunkSize,\n logger,\n overrides,\n );\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeEventStream(res, events, {\n latency,\n streamingProfile: fixture.streamingProfile,\n signal: interruption?.signal,\n onChunkSent: interruption?.tick,\n });\n if (!completed) {\n if (!res.writableEnded) res.destroy();\n journalEntry.response.interrupted = true;\n journalEntry.response.interruptReason = interruption?.reason();\n }\n interruption?.cleanup();\n return;\n }\n\n // Unknown response type\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 500, fixture },\n });\n writeErrorResponse(\n res,\n 500,\n JSON.stringify({\n error: {\n message: \"Fixture response did not match any known type\",\n type: \"server_error\",\n },\n }),\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"bedrock-converse.js","names":[],"sources":["../src/bedrock-converse.ts"],"sourcesContent":["/**\n * AWS Bedrock Converse API support.\n *\n * Translates incoming Converse and Converse-stream requests (Bedrock Converse\n * format) into the ChatCompletionRequest format used by the fixture router,\n * and converts fixture responses back into Converse API format — either a\n * single JSON response or an Event Stream binary stream.\n */\n\nimport type * as http from \"node:http\";\nimport type {\n ChatCompletionRequest,\n ChatMessage,\n Fixture,\n HandlerDefaults,\n ResponseOverrides,\n ToolCall,\n ToolDefinition,\n} from \"./types.js\";\nimport {\n generateToolUseId,\n extractOverrides,\n isTextResponse,\n isToolCallResponse,\n isContentWithToolCallsResponse,\n isErrorResponse,\n flattenHeaders,\n getTestId,\n resolveResponse,\n resolveStrictMode,\n strictOverrideField,\n} from \"./helpers.js\";\nimport { matchFixture } from \"./router.js\";\nimport { writeErrorResponse } from \"./sse-writer.js\";\nimport { writeEventStream } from \"./aws-event-stream.js\";\nimport { createInterruptionSignal } from \"./interruption.js\";\nimport type { Journal } from \"./journal.js\";\nimport type { Logger } from \"./logger.js\";\nimport { applyChaos } from \"./chaos.js\";\nimport { proxyAndRecord } from \"./recorder.js\";\n\n// ─── Converse request types ─────────────────────────────────────────────────\n\ninterface ConverseContentBlock {\n text?: string;\n toolUse?: { toolUseId: string; name: string; input: object };\n toolResult?: { toolUseId: string; content: { text?: string }[] };\n}\n\ninterface ConverseMessage {\n role: \"user\" | \"assistant\";\n content: ConverseContentBlock[];\n}\n\ninterface ConverseToolSpec {\n name: string;\n description?: string;\n inputSchema?: object;\n}\n\ninterface ConverseRequest {\n messages: ConverseMessage[];\n system?: { text: string }[];\n inferenceConfig?: { maxTokens?: number; temperature?: number };\n toolConfig?: { tools: { toolSpec: ConverseToolSpec }[] };\n}\n\n// ─── Converse stop_reason mapping ──────────────────────────────────────────\n\nfunction converseStopReason(\n overrideFinishReason: string | undefined,\n defaultReason: string,\n): string {\n if (!overrideFinishReason) return defaultReason;\n if (overrideFinishReason === \"stop\") return \"end_turn\";\n if (overrideFinishReason === \"tool_calls\") return \"tool_use\";\n if (overrideFinishReason === \"length\") return \"max_tokens\";\n return overrideFinishReason;\n}\n\n/**\n * Build Converse-format usage from fixture overrides.\n *\n * When no overrides are provided (the common case for mocks), all token\n * counts default to zero. This is intentional — aimock is a mock server\n * and does not perform real tokenisation. Callers that need non-zero\n * usage should supply explicit `usage` overrides in their fixture.\n */\nfunction converseUsage(overrides?: ResponseOverrides): {\n inputTokens: number;\n outputTokens: number;\n totalTokens: number;\n} {\n if (!overrides?.usage) return { inputTokens: 0, outputTokens: 0, totalTokens: 0 };\n const inputTokens = overrides.usage.input_tokens ?? overrides.usage.prompt_tokens ?? 0;\n const outputTokens = overrides.usage.output_tokens ?? overrides.usage.completion_tokens ?? 0;\n return { inputTokens, outputTokens, totalTokens: inputTokens + outputTokens };\n}\n\nfunction parseConverseToolArgumentsForStream(toolCall: ToolCall, logger: Logger): string {\n try {\n const parsed = JSON.parse(toolCall.arguments || \"{}\");\n return JSON.stringify(parsed);\n } catch {\n logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${toolCall.name}\": ${toolCall.arguments}`,\n );\n return \"{}\";\n }\n}\n\nfunction buildBedrockStreamTextEvents(\n content: string,\n chunkSize: number,\n reasoning?: string,\n overrides?: ResponseOverrides,\n): Array<{ eventType: string; payload: object }> {\n const events: Array<{ eventType: string; payload: object }> = [\n { eventType: \"messageStart\", payload: { role: \"assistant\" } },\n ];\n\n if (reasoning) {\n const blockIndex = 0;\n events.push({\n eventType: \"contentBlockStart\",\n payload: { contentBlockIndex: blockIndex, start: { reasoningContent: {} } },\n });\n for (let i = 0; i < reasoning.length; i += chunkSize) {\n events.push({\n eventType: \"contentBlockDelta\",\n payload: {\n contentBlockIndex: blockIndex,\n delta: { reasoningContent: { text: reasoning.slice(i, i + chunkSize) } },\n },\n });\n }\n events.push({\n eventType: \"contentBlockStop\",\n payload: { contentBlockIndex: blockIndex },\n });\n }\n\n const textBlockIndex = reasoning ? 1 : 0;\n events.push({\n eventType: \"contentBlockStart\",\n payload: { contentBlockIndex: textBlockIndex, start: {} },\n });\n for (let i = 0; i < content.length; i += chunkSize) {\n events.push({\n eventType: \"contentBlockDelta\",\n payload: {\n contentBlockIndex: textBlockIndex,\n delta: { text: content.slice(i, i + chunkSize) },\n },\n });\n }\n events.push({\n eventType: \"contentBlockStop\",\n payload: { contentBlockIndex: textBlockIndex },\n });\n events.push({\n eventType: \"messageStop\",\n payload: { stopReason: converseStopReason(overrides?.finishReason, \"end_turn\") },\n });\n const usage = converseUsage(overrides);\n events.push({\n eventType: \"metadata\",\n payload: { usage, metrics: { latencyMs: 0 } },\n });\n return events;\n}\n\nfunction buildBedrockStreamContentWithToolCallsEvents(\n content: string,\n toolCalls: ToolCall[],\n chunkSize: number,\n logger: Logger,\n reasoning?: string,\n overrides?: ResponseOverrides,\n): Array<{ eventType: string; payload: object }> {\n const events = buildBedrockStreamTextEvents(content, chunkSize, reasoning, overrides);\n // Remove trailing metadata + messageStop events — we re-emit them after tool blocks\n for (let i = events.length - 1; i >= 0; i--) {\n const et = (events[i] as { eventType: string }).eventType;\n if (et === \"metadata\" || et === \"messageStop\") {\n events.splice(i, 1);\n }\n }\n let blockIndex = reasoning ? 2 : 1;\n\n for (const tc of toolCalls) {\n const toolUseId = tc.id || generateToolUseId();\n events.push({\n eventType: \"contentBlockStart\",\n payload: {\n contentBlockIndex: blockIndex,\n start: { toolUse: { toolUseId, name: tc.name } },\n },\n });\n const argsStr = parseConverseToolArgumentsForStream(tc, logger);\n for (let i = 0; i < argsStr.length; i += chunkSize) {\n events.push({\n eventType: \"contentBlockDelta\",\n payload: {\n contentBlockIndex: blockIndex,\n delta: { toolUse: { input: argsStr.slice(i, i + chunkSize) } },\n },\n });\n }\n events.push({\n eventType: \"contentBlockStop\",\n payload: { contentBlockIndex: blockIndex },\n });\n blockIndex++;\n }\n events.push({\n eventType: \"messageStop\",\n payload: { stopReason: converseStopReason(overrides?.finishReason, \"tool_use\") },\n });\n const usage = converseUsage(overrides);\n events.push({\n eventType: \"metadata\",\n payload: { usage, metrics: { latencyMs: 0 } },\n });\n return events;\n}\n\nfunction buildBedrockStreamToolCallEvents(\n toolCalls: ToolCall[],\n chunkSize: number,\n logger: Logger,\n overrides?: ResponseOverrides,\n): Array<{ eventType: string; payload: object }> {\n const events: Array<{ eventType: string; payload: object }> = [\n { eventType: \"messageStart\", payload: { role: \"assistant\" } },\n ];\n\n for (let tcIdx = 0; tcIdx < toolCalls.length; tcIdx++) {\n const tc = toolCalls[tcIdx];\n const toolUseId = tc.id || generateToolUseId();\n events.push({\n eventType: \"contentBlockStart\",\n payload: {\n contentBlockIndex: tcIdx,\n start: { toolUse: { toolUseId, name: tc.name } },\n },\n });\n const argsStr = parseConverseToolArgumentsForStream(tc, logger);\n for (let i = 0; i < argsStr.length; i += chunkSize) {\n events.push({\n eventType: \"contentBlockDelta\",\n payload: {\n contentBlockIndex: tcIdx,\n delta: { toolUse: { input: argsStr.slice(i, i + chunkSize) } },\n },\n });\n }\n events.push({\n eventType: \"contentBlockStop\",\n payload: { contentBlockIndex: tcIdx },\n });\n }\n events.push({\n eventType: \"messageStop\",\n payload: { stopReason: converseStopReason(overrides?.finishReason, \"tool_use\") },\n });\n const usage = converseUsage(overrides);\n events.push({\n eventType: \"metadata\",\n payload: { usage, metrics: { latencyMs: 0 } },\n });\n return events;\n}\n\n// ─── Input conversion: Converse → ChatCompletionRequest ─────────────────────\n\nexport function converseToCompletionRequest(\n req: ConverseRequest,\n modelId: string,\n logger?: Logger,\n): ChatCompletionRequest {\n const messages: ChatMessage[] = [];\n\n // system field → system message\n if (req.system && req.system.length > 0) {\n const systemText = req.system.map((s) => s.text).join(\"\");\n if (systemText) {\n messages.push({ role: \"system\", content: systemText });\n }\n }\n\n for (const msg of req.messages) {\n if (msg.role === \"user\") {\n // Check for toolResult blocks\n const toolResults = msg.content.filter((b) => b.toolResult);\n const textBlocks = msg.content.filter(\n (b) => b.text !== undefined && b.text !== \"\" && !b.toolResult,\n );\n const unsupportedBlocks = msg.content.filter(\n (b) => b.text === undefined && !b.toolResult && !b.toolUse,\n );\n if (unsupportedBlocks.length > 0 && logger) {\n logger.warn(\n `Converse user message contains unsupported content block types — these will be dropped during conversion`,\n );\n }\n\n if (toolResults.length > 0) {\n for (const block of toolResults) {\n const tr = block.toolResult!;\n const resultContent = tr.content.map((c) => c.text ?? \"\").join(\"\");\n messages.push({\n role: \"tool\",\n content: resultContent,\n tool_call_id: tr.toolUseId,\n });\n }\n if (textBlocks.length > 0) {\n messages.push({\n role: \"user\",\n content: textBlocks.map((b) => b.text ?? \"\").join(\"\"),\n });\n }\n continue;\n }\n\n // Plain user message\n const text = msg.content\n .filter((b) => b.text !== undefined && b.text !== \"\")\n .map((b) => b.text ?? \"\")\n .join(\"\");\n messages.push({ role: \"user\", content: text });\n } else if (msg.role === \"assistant\") {\n const toolUseBlocks = msg.content.filter((b) => b.toolUse);\n const textContent = msg.content\n .filter((b) => b.text !== undefined && b.text !== \"\")\n .map((b) => b.text ?? \"\")\n .join(\"\");\n\n if (toolUseBlocks.length > 0) {\n messages.push({\n role: \"assistant\",\n content: textContent || null,\n tool_calls: toolUseBlocks.map((b) => ({\n id: b.toolUse!.toolUseId,\n type: \"function\" as const,\n function: {\n name: b.toolUse!.name,\n arguments: JSON.stringify(b.toolUse!.input),\n },\n })),\n });\n } else {\n messages.push({ role: \"assistant\", content: textContent || null });\n }\n } else {\n const warnMsg = `Unexpected message role \"${msg.role}\" in Converse request — skipping`;\n if (logger) {\n logger.warn(warnMsg);\n }\n }\n }\n\n // Convert tools\n let tools: ToolDefinition[] | undefined;\n if (req.toolConfig?.tools && req.toolConfig.tools.length > 0) {\n tools = req.toolConfig.tools.map((t) => ({\n type: \"function\" as const,\n function: {\n name: t.toolSpec.name,\n description: t.toolSpec.description,\n parameters: (t.toolSpec.inputSchema && \"json\" in t.toolSpec.inputSchema\n ? (t.toolSpec.inputSchema as Record<string, unknown>).json\n : t.toolSpec.inputSchema) as object | undefined,\n },\n }));\n }\n\n return {\n model: modelId,\n messages,\n stream: false,\n temperature: req.inferenceConfig?.temperature,\n max_tokens: req.inferenceConfig?.maxTokens,\n tools,\n };\n}\n\n// ─── Response builders ──────────────────────────────────────────────────────\n\nfunction buildConverseTextResponse(\n content: string,\n reasoning?: string,\n overrides?: ResponseOverrides,\n): object {\n const contentBlocks: object[] = [];\n if (reasoning) {\n contentBlocks.push({\n reasoningContent: { reasoningText: { text: reasoning } },\n });\n }\n contentBlocks.push({ text: content });\n\n return {\n output: {\n message: {\n role: \"assistant\",\n content: contentBlocks,\n },\n },\n stopReason: converseStopReason(overrides?.finishReason, \"end_turn\"),\n usage: converseUsage(overrides),\n metrics: { latencyMs: 0 },\n };\n}\n\nfunction buildConverseToolCallResponse(\n toolCalls: ToolCall[],\n logger: Logger,\n overrides?: ResponseOverrides,\n): object {\n return {\n output: {\n message: {\n role: \"assistant\",\n content: toolCalls.map((tc) => {\n let argsObj: unknown;\n try {\n argsObj = JSON.parse(tc.arguments || \"{}\");\n } catch {\n logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n );\n argsObj = {};\n }\n return {\n toolUse: {\n toolUseId: tc.id || generateToolUseId(),\n name: tc.name,\n input: argsObj,\n },\n };\n }),\n },\n },\n stopReason: converseStopReason(overrides?.finishReason, \"tool_use\"),\n usage: converseUsage(overrides),\n metrics: { latencyMs: 0 },\n };\n}\n\nfunction buildConverseContentWithToolCallsResponse(\n content: string,\n toolCalls: ToolCall[],\n logger: Logger,\n reasoning?: string,\n overrides?: ResponseOverrides,\n): object {\n const contentBlocks: object[] = [];\n if (reasoning) {\n contentBlocks.push({\n reasoningContent: { reasoningText: { text: reasoning } },\n });\n }\n contentBlocks.push({ text: content });\n for (const tc of toolCalls) {\n let argsObj: unknown;\n try {\n argsObj = JSON.parse(tc.arguments || \"{}\");\n } catch {\n logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n );\n argsObj = {};\n }\n contentBlocks.push({\n toolUse: {\n toolUseId: tc.id || generateToolUseId(),\n name: tc.name,\n input: argsObj,\n },\n });\n }\n\n return {\n output: {\n message: {\n role: \"assistant\",\n content: contentBlocks,\n },\n },\n stopReason: converseStopReason(overrides?.finishReason, \"tool_use\"),\n usage: converseUsage(overrides),\n metrics: { latencyMs: 0 },\n };\n}\n\n// ─── Request handlers ───────────────────────────────────────────────────────\n\nexport async function handleConverse(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n raw: string,\n modelId: string,\n fixtures: Fixture[],\n journal: Journal,\n defaults: HandlerDefaults,\n setCorsHeaders: (res: http.ServerResponse) => void,\n): Promise<void> {\n const { logger } = defaults;\n setCorsHeaders(res);\n\n const urlPath = req.url ?? `/model/${modelId}/converse`;\n\n let converseReq: ConverseRequest;\n try {\n converseReq = JSON.parse(raw) as ConverseRequest;\n } catch (parseErr) {\n const detail = parseErr instanceof Error ? parseErr.message : \"unknown\";\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: {\n message: `Malformed JSON: ${detail}`,\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n if (!converseReq.messages || !Array.isArray(converseReq.messages)) {\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: {\n message: \"Invalid request: messages array is required\",\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n const completionReq = converseToCompletionRequest(converseReq, modelId, logger);\n completionReq._endpointType = \"chat\";\n\n const testId = getTestId(req);\n const fixture = matchFixture(\n fixtures,\n completionReq,\n journal.getFixtureMatchCountsForTest(testId),\n defaults.requestTransform,\n );\n\n if (fixture) {\n logger.debug(`Fixture matched: ${JSON.stringify(fixture.match).slice(0, 120)}`);\n } else {\n logger.debug(`No fixture matched for request`);\n }\n\n if (fixture) {\n journal.incrementFixtureMatchCount(fixture, fixtures, testId);\n }\n\n if (\n applyChaos(\n res,\n fixture,\n defaults.chaos,\n req.headers,\n journal,\n {\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n },\n fixture ? \"fixture\" : \"proxy\",\n defaults.registry,\n defaults.logger,\n )\n )\n return;\n\n if (!fixture) {\n const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);\n if (effectiveStrict) {\n const strictStatus = 503;\n const strictMessage = \"Strict mode: no fixture matched\";\n logger.error(`STRICT: No fixture matched for ${req.method ?? \"POST\"} ${urlPath}`);\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: {\n status: strictStatus,\n fixture: null,\n ...strictOverrideField(defaults.strict, req.headers),\n },\n });\n writeErrorResponse(\n res,\n strictStatus,\n JSON.stringify({\n error: {\n message: strictMessage,\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n if (defaults.record) {\n const outcome = await proxyAndRecord(\n req,\n res,\n completionReq,\n \"bedrock\",\n urlPath,\n fixtures,\n defaults,\n raw,\n );\n if (outcome === \"handled_by_hook\") return;\n if (outcome !== \"not_configured\") {\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: res.statusCode ?? 200, fixture: null, source: \"proxy\" },\n });\n return;\n }\n }\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: {\n status: 404,\n fixture: null,\n ...strictOverrideField(defaults.strict, req.headers),\n },\n });\n writeErrorResponse(\n res,\n 404,\n JSON.stringify({\n error: {\n message: \"No fixture matched\",\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n const response = await resolveResponse(fixture, completionReq);\n\n // Error response\n if (isErrorResponse(response)) {\n const status = response.status ?? 500;\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status, fixture },\n });\n const errBody = {\n type: \"error\",\n error: {\n type: response.error.type ?? \"invalid_request_error\",\n message: response.error.message,\n },\n };\n writeErrorResponse(res, status, JSON.stringify(errBody));\n return;\n }\n\n // Content + tool calls response\n if (isContentWithToolCallsResponse(response)) {\n if (response.webSearches?.length) {\n logger.warn(\n \"webSearches in fixture response are not supported for Bedrock Converse API — ignoring\",\n );\n }\n const overrides = extractOverrides(response);\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n const body = buildConverseContentWithToolCallsResponse(\n response.content,\n response.toolCalls,\n logger,\n response.reasoning,\n overrides,\n );\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n return;\n }\n\n // Text response\n if (isTextResponse(response)) {\n if (response.webSearches?.length) {\n logger.warn(\n \"webSearches in fixture response are not supported for Bedrock Converse API — ignoring\",\n );\n }\n const overrides = extractOverrides(response);\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n const body = buildConverseTextResponse(response.content, response.reasoning, overrides);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n return;\n }\n\n // Tool call response\n if (isToolCallResponse(response)) {\n if (response.webSearches?.length) {\n logger.warn(\n \"webSearches in fixture response are not supported for Bedrock Converse API — ignoring\",\n );\n }\n const overrides = extractOverrides(response);\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n const body = buildConverseToolCallResponse(response.toolCalls, logger, overrides);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n return;\n }\n\n // Unknown response type\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 500, fixture },\n });\n writeErrorResponse(\n res,\n 500,\n JSON.stringify({\n error: {\n message: \"Fixture response did not match any known type\",\n type: \"server_error\",\n },\n }),\n );\n}\n\nexport async function handleConverseStream(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n raw: string,\n modelId: string,\n fixtures: Fixture[],\n journal: Journal,\n defaults: HandlerDefaults,\n setCorsHeaders: (res: http.ServerResponse) => void,\n): Promise<void> {\n const { logger } = defaults;\n setCorsHeaders(res);\n\n const urlPath = req.url ?? `/model/${modelId}/converse-stream`;\n\n let converseReq: ConverseRequest;\n try {\n converseReq = JSON.parse(raw) as ConverseRequest;\n } catch (parseErr) {\n const detail = parseErr instanceof Error ? parseErr.message : \"unknown\";\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: {\n message: `Malformed JSON: ${detail}`,\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n if (!converseReq.messages || !Array.isArray(converseReq.messages)) {\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: {\n message: \"Invalid request: messages array is required\",\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n const completionReq = converseToCompletionRequest(converseReq, modelId, logger);\n completionReq.stream = true;\n completionReq._endpointType = \"chat\";\n\n const testId = getTestId(req);\n const fixture = matchFixture(\n fixtures,\n completionReq,\n journal.getFixtureMatchCountsForTest(testId),\n defaults.requestTransform,\n );\n\n if (fixture) {\n logger.debug(`Fixture matched: ${JSON.stringify(fixture.match).slice(0, 120)}`);\n } else {\n logger.debug(`No fixture matched for request`);\n }\n\n if (fixture) {\n journal.incrementFixtureMatchCount(fixture, fixtures, testId);\n }\n\n if (\n applyChaos(\n res,\n fixture,\n defaults.chaos,\n req.headers,\n journal,\n {\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n },\n fixture ? \"fixture\" : \"proxy\",\n defaults.registry,\n defaults.logger,\n )\n )\n return;\n\n if (!fixture) {\n const effectiveStrict = resolveStrictMode(defaults.strict, req.headers);\n if (effectiveStrict) {\n const strictStatus = 503;\n const strictMessage = \"Strict mode: no fixture matched\";\n logger.error(`STRICT: No fixture matched for ${req.method ?? \"POST\"} ${urlPath}`);\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: {\n status: strictStatus,\n fixture: null,\n ...strictOverrideField(defaults.strict, req.headers),\n },\n });\n writeErrorResponse(\n res,\n strictStatus,\n JSON.stringify({\n error: {\n message: strictMessage,\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n if (defaults.record) {\n const outcome = await proxyAndRecord(\n req,\n res,\n completionReq,\n \"bedrock\",\n urlPath,\n fixtures,\n defaults,\n raw,\n );\n if (outcome === \"handled_by_hook\") return;\n if (outcome !== \"not_configured\") {\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: res.statusCode ?? 200, fixture: null, source: \"proxy\" },\n });\n return;\n }\n }\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: {\n status: 404,\n fixture: null,\n ...strictOverrideField(defaults.strict, req.headers),\n },\n });\n writeErrorResponse(\n res,\n 404,\n JSON.stringify({\n error: {\n message: \"No fixture matched\",\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n const response = await resolveResponse(fixture, completionReq);\n const latency = fixture.latency ?? defaults.latency;\n const chunkSize = Math.max(1, fixture.chunkSize ?? defaults.chunkSize);\n\n // Error response\n if (isErrorResponse(response)) {\n const status = response.status ?? 500;\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status, fixture },\n });\n const errBody = {\n type: \"error\",\n error: {\n type: response.error.type ?? \"invalid_request_error\",\n message: response.error.message,\n },\n };\n writeErrorResponse(res, status, JSON.stringify(errBody));\n return;\n }\n\n // Content + tool calls response — stream as Event Stream\n if (isContentWithToolCallsResponse(response)) {\n if (response.webSearches?.length) {\n logger.warn(\n \"webSearches in fixture response are not supported for Bedrock Converse API — ignoring\",\n );\n }\n const overrides = extractOverrides(response);\n const journalEntry = journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n const events = buildBedrockStreamContentWithToolCallsEvents(\n response.content,\n response.toolCalls,\n chunkSize,\n logger,\n response.reasoning,\n overrides,\n );\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeEventStream(res, events, {\n latency,\n streamingProfile: fixture.streamingProfile,\n signal: interruption?.signal,\n onChunkSent: interruption?.tick,\n });\n if (!completed) {\n if (!res.writableEnded) res.destroy();\n journalEntry.response.interrupted = true;\n journalEntry.response.interruptReason = interruption?.reason();\n }\n interruption?.cleanup();\n return;\n }\n\n // Text response — stream as Event Stream\n if (isTextResponse(response)) {\n if (response.webSearches?.length) {\n logger.warn(\n \"webSearches in fixture response are not supported for Bedrock Converse API — ignoring\",\n );\n }\n const overrides = extractOverrides(response);\n const journalEntry = journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n const events = buildBedrockStreamTextEvents(\n response.content,\n chunkSize,\n response.reasoning,\n overrides,\n );\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeEventStream(res, events, {\n latency,\n streamingProfile: fixture.streamingProfile,\n signal: interruption?.signal,\n onChunkSent: interruption?.tick,\n });\n if (!completed) {\n if (!res.writableEnded) res.destroy();\n journalEntry.response.interrupted = true;\n journalEntry.response.interruptReason = interruption?.reason();\n }\n interruption?.cleanup();\n return;\n }\n\n // Tool call response — stream as Event Stream\n if (isToolCallResponse(response)) {\n if (response.webSearches?.length) {\n logger.warn(\n \"webSearches in fixture response are not supported for Bedrock Converse API — ignoring\",\n );\n }\n const overrides = extractOverrides(response);\n const journalEntry = journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 200, fixture },\n });\n const events = buildBedrockStreamToolCallEvents(\n response.toolCalls,\n chunkSize,\n logger,\n overrides,\n );\n const interruption = createInterruptionSignal(fixture);\n const completed = await writeEventStream(res, events, {\n latency,\n streamingProfile: fixture.streamingProfile,\n signal: interruption?.signal,\n onChunkSent: interruption?.tick,\n });\n if (!completed) {\n if (!res.writableEnded) res.destroy();\n journalEntry.response.interrupted = true;\n journalEntry.response.interruptReason = interruption?.reason();\n }\n interruption?.cleanup();\n return;\n }\n\n // Unknown response type\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: completionReq,\n response: { status: 500, fixture },\n });\n writeErrorResponse(\n res,\n 500,\n JSON.stringify({\n error: {\n message: \"Fixture response did not match any known type\",\n type: \"server_error\",\n },\n }),\n );\n}\n"],"mappings":"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"}
|
package/dist/bedrock.cjs
CHANGED
|
@@ -84,7 +84,7 @@ function bedrockToCompletionRequest(req, modelId, logger) {
|
|
|
84
84
|
const textContent = extractTextContent(msg.content);
|
|
85
85
|
if (toolUseBlocks.length > 0) messages.push({
|
|
86
86
|
role: "assistant",
|
|
87
|
-
content: textContent
|
|
87
|
+
content: textContent || null,
|
|
88
88
|
tool_calls: toolUseBlocks.map((b, index) => {
|
|
89
89
|
if (!b.id && logger) logger.warn(`Bedrock assistant tool_use block at index ${index} is missing an id — using deterministic fallback "tool_use_${index}"`);
|
|
90
90
|
return {
|
|
@@ -99,7 +99,7 @@ function bedrockToCompletionRequest(req, modelId, logger) {
|
|
|
99
99
|
});
|
|
100
100
|
else messages.push({
|
|
101
101
|
role: "assistant",
|
|
102
|
-
content: textContent
|
|
102
|
+
content: textContent || null
|
|
103
103
|
});
|
|
104
104
|
} else messages.push({
|
|
105
105
|
role: "assistant",
|
|
@@ -120,6 +120,7 @@ function bedrockToCompletionRequest(req, modelId, logger) {
|
|
|
120
120
|
messages,
|
|
121
121
|
stream: false,
|
|
122
122
|
temperature: req.temperature,
|
|
123
|
+
max_tokens: req.max_tokens,
|
|
123
124
|
tools
|
|
124
125
|
};
|
|
125
126
|
}
|
|
@@ -227,8 +228,31 @@ async function handleBedrock(req, res, raw, modelId, fixtures, journal, defaults
|
|
|
227
228
|
body: completionReq
|
|
228
229
|
}, fixture ? "fixture" : "proxy", defaults.registry, defaults.logger)) return;
|
|
229
230
|
if (!fixture) {
|
|
231
|
+
if (require_helpers.resolveStrictMode(defaults.strict, req.headers)) {
|
|
232
|
+
const strictStatus = 503;
|
|
233
|
+
const strictMessage = "Strict mode: no fixture matched";
|
|
234
|
+
logger.error(`STRICT: No fixture matched for ${req.method ?? "POST"} ${urlPath}`);
|
|
235
|
+
journal.add({
|
|
236
|
+
method: req.method ?? "POST",
|
|
237
|
+
path: urlPath,
|
|
238
|
+
headers: require_helpers.flattenHeaders(req.headers),
|
|
239
|
+
body: completionReq,
|
|
240
|
+
response: {
|
|
241
|
+
status: strictStatus,
|
|
242
|
+
fixture: null,
|
|
243
|
+
...require_helpers.strictOverrideField(defaults.strict, req.headers)
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
require_sse_writer.writeErrorResponse(res, strictStatus, JSON.stringify({ error: {
|
|
247
|
+
message: strictMessage,
|
|
248
|
+
type: "invalid_request_error"
|
|
249
|
+
} }));
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
230
252
|
if (defaults.record) {
|
|
231
|
-
|
|
253
|
+
const outcome = await require_recorder.proxyAndRecord(req, res, completionReq, "bedrock", urlPath, fixtures, defaults, raw);
|
|
254
|
+
if (outcome === "handled_by_hook") return;
|
|
255
|
+
if (outcome !== "not_configured") {
|
|
232
256
|
journal.add({
|
|
233
257
|
method: req.method ?? "POST",
|
|
234
258
|
path: urlPath,
|
|
@@ -243,23 +267,19 @@ async function handleBedrock(req, res, raw, modelId, fixtures, journal, defaults
|
|
|
243
267
|
return;
|
|
244
268
|
}
|
|
245
269
|
}
|
|
246
|
-
const effectiveStrict = require_helpers.resolveStrictMode(defaults.strict, req.headers);
|
|
247
|
-
const strictStatus = effectiveStrict ? 503 : 404;
|
|
248
|
-
const strictMessage = effectiveStrict ? "Strict mode: no fixture matched" : "No fixture matched";
|
|
249
|
-
if (effectiveStrict) logger.error(`STRICT: No fixture matched for ${req.method ?? "POST"} ${urlPath}`);
|
|
250
270
|
journal.add({
|
|
251
271
|
method: req.method ?? "POST",
|
|
252
272
|
path: urlPath,
|
|
253
273
|
headers: require_helpers.flattenHeaders(req.headers),
|
|
254
274
|
body: completionReq,
|
|
255
275
|
response: {
|
|
256
|
-
status:
|
|
276
|
+
status: 404,
|
|
257
277
|
fixture: null,
|
|
258
278
|
...require_helpers.strictOverrideField(defaults.strict, req.headers)
|
|
259
279
|
}
|
|
260
280
|
});
|
|
261
|
-
require_sse_writer.writeErrorResponse(res,
|
|
262
|
-
message:
|
|
281
|
+
require_sse_writer.writeErrorResponse(res, 404, JSON.stringify({ error: {
|
|
282
|
+
message: "No fixture matched",
|
|
263
283
|
type: "invalid_request_error"
|
|
264
284
|
} }));
|
|
265
285
|
return;
|
|
@@ -330,7 +350,7 @@ async function handleBedrock(req, res, raw, modelId, fixtures, journal, defaults
|
|
|
330
350
|
return;
|
|
331
351
|
}
|
|
332
352
|
if (require_helpers.isToolCallResponse(response)) {
|
|
333
|
-
if (
|
|
353
|
+
if (response.webSearches?.length) logger.warn("webSearches in fixture response are not supported for Bedrock API — ignoring");
|
|
334
354
|
const overrides = require_helpers.extractOverrides(response);
|
|
335
355
|
journal.add({
|
|
336
356
|
method: req.method ?? "POST",
|
|
@@ -727,8 +747,31 @@ async function handleBedrockStream(req, res, raw, modelId, fixtures, journal, de
|
|
|
727
747
|
body: completionReq
|
|
728
748
|
}, fixture ? "fixture" : "proxy", defaults.registry, defaults.logger)) return;
|
|
729
749
|
if (!fixture) {
|
|
750
|
+
if (require_helpers.resolveStrictMode(defaults.strict, req.headers)) {
|
|
751
|
+
const strictStatus = 503;
|
|
752
|
+
const strictMessage = "Strict mode: no fixture matched";
|
|
753
|
+
logger.error(`STRICT: No fixture matched for ${req.method ?? "POST"} ${urlPath}`);
|
|
754
|
+
journal.add({
|
|
755
|
+
method: req.method ?? "POST",
|
|
756
|
+
path: urlPath,
|
|
757
|
+
headers: require_helpers.flattenHeaders(req.headers),
|
|
758
|
+
body: completionReq,
|
|
759
|
+
response: {
|
|
760
|
+
status: strictStatus,
|
|
761
|
+
fixture: null,
|
|
762
|
+
...require_helpers.strictOverrideField(defaults.strict, req.headers)
|
|
763
|
+
}
|
|
764
|
+
});
|
|
765
|
+
require_sse_writer.writeErrorResponse(res, strictStatus, JSON.stringify({ error: {
|
|
766
|
+
message: strictMessage,
|
|
767
|
+
type: "invalid_request_error"
|
|
768
|
+
} }));
|
|
769
|
+
return;
|
|
770
|
+
}
|
|
730
771
|
if (defaults.record) {
|
|
731
|
-
|
|
772
|
+
const outcome = await require_recorder.proxyAndRecord(req, res, completionReq, "bedrock", urlPath, fixtures, defaults, raw);
|
|
773
|
+
if (outcome === "handled_by_hook") return;
|
|
774
|
+
if (outcome !== "not_configured") {
|
|
732
775
|
journal.add({
|
|
733
776
|
method: req.method ?? "POST",
|
|
734
777
|
path: urlPath,
|
|
@@ -743,23 +786,19 @@ async function handleBedrockStream(req, res, raw, modelId, fixtures, journal, de
|
|
|
743
786
|
return;
|
|
744
787
|
}
|
|
745
788
|
}
|
|
746
|
-
const effectiveStrict = require_helpers.resolveStrictMode(defaults.strict, req.headers);
|
|
747
|
-
const strictStatus = effectiveStrict ? 503 : 404;
|
|
748
|
-
const strictMessage = effectiveStrict ? "Strict mode: no fixture matched" : "No fixture matched";
|
|
749
|
-
if (effectiveStrict) logger.error(`STRICT: No fixture matched for ${req.method ?? "POST"} ${urlPath}`);
|
|
750
789
|
journal.add({
|
|
751
790
|
method: req.method ?? "POST",
|
|
752
791
|
path: urlPath,
|
|
753
792
|
headers: require_helpers.flattenHeaders(req.headers),
|
|
754
793
|
body: completionReq,
|
|
755
794
|
response: {
|
|
756
|
-
status:
|
|
795
|
+
status: 404,
|
|
757
796
|
fixture: null,
|
|
758
797
|
...require_helpers.strictOverrideField(defaults.strict, req.headers)
|
|
759
798
|
}
|
|
760
799
|
});
|
|
761
|
-
require_sse_writer.writeErrorResponse(res,
|
|
762
|
-
message:
|
|
800
|
+
require_sse_writer.writeErrorResponse(res, 404, JSON.stringify({ error: {
|
|
801
|
+
message: "No fixture matched",
|
|
763
802
|
type: "invalid_request_error"
|
|
764
803
|
} }));
|
|
765
804
|
return;
|
|
@@ -846,7 +885,7 @@ async function handleBedrockStream(req, res, raw, modelId, fixtures, journal, de
|
|
|
846
885
|
return;
|
|
847
886
|
}
|
|
848
887
|
if (require_helpers.isToolCallResponse(response)) {
|
|
849
|
-
if (
|
|
888
|
+
if (response.webSearches?.length) logger.warn("webSearches in fixture response are not supported for Bedrock API — ignoring");
|
|
850
889
|
const overrides = require_helpers.extractOverrides(response);
|
|
851
890
|
const journalEntry = journal.add({
|
|
852
891
|
method: req.method ?? "POST",
|