@copilotkit/aimock 1.16.0 → 1.16.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/bedrock-converse.cjs +4 -0
- 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 +4 -0
- package/dist/bedrock-converse.js.map +1 -1
- package/dist/bedrock.cjs +4 -0
- 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 +4 -0
- package/dist/bedrock.js.map +1 -1
- package/dist/cohere.cjs +4 -1
- package/dist/cohere.cjs.map +1 -1
- package/dist/cohere.js +4 -1
- package/dist/cohere.js.map +1 -1
- package/dist/embeddings.cjs +4 -1
- package/dist/embeddings.cjs.map +1 -1
- package/dist/embeddings.js +4 -1
- package/dist/embeddings.js.map +1 -1
- package/dist/gemini.cjs +2 -0
- package/dist/gemini.cjs.map +1 -1
- package/dist/gemini.js +2 -0
- package/dist/gemini.js.map +1 -1
- package/dist/images.cjs +4 -1
- package/dist/images.cjs.map +1 -1
- package/dist/images.js +4 -1
- package/dist/images.js.map +1 -1
- package/dist/messages.cjs +8 -1
- package/dist/messages.cjs.map +1 -1
- package/dist/messages.js +8 -1
- package/dist/messages.js.map +1 -1
- package/dist/ollama.cjs +8 -2
- 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 +8 -2
- package/dist/ollama.js.map +1 -1
- package/dist/responses.cjs +87 -13
- package/dist/responses.cjs.map +1 -1
- package/dist/responses.d.cts.map +1 -1
- package/dist/responses.d.ts.map +1 -1
- package/dist/responses.js +87 -13
- package/dist/responses.js.map +1 -1
- package/dist/server.cjs +8 -1
- 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 +8 -1
- package/dist/server.js.map +1 -1
- package/dist/speech.cjs +4 -1
- package/dist/speech.cjs.map +1 -1
- package/dist/speech.js +4 -1
- package/dist/speech.js.map +1 -1
- package/dist/transcription.cjs +4 -1
- package/dist/transcription.cjs.map +1 -1
- package/dist/transcription.js +4 -1
- package/dist/transcription.js.map +1 -1
- package/dist/video.cjs +4 -1
- package/dist/video.cjs.map +1 -1
- package/dist/video.d.cts.map +1 -1
- package/dist/video.d.ts.map +1 -1
- package/dist/video.js +4 -1
- package/dist/video.js.map +1 -1
- package/package.json +1 -1
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"source": {
|
|
10
10
|
"source": "npm",
|
|
11
11
|
"package": "@copilotkit/aimock",
|
|
12
|
-
"version": "^1.
|
|
12
|
+
"version": "^1.16.0"
|
|
13
13
|
},
|
|
14
14
|
"description": "Fixture authoring skill for @copilotkit/aimock — LLM, multimedia (image/TTS/transcription/video), MCP, A2A, AG-UI, vector, embeddings, structured output, sequential responses, streaming physics, record/replay, agent loop patterns, and debugging"
|
|
15
15
|
}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @copilotkit/aimock
|
|
2
2
|
|
|
3
|
+
## [1.16.1] - 2026-04-28
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **Responses API: item_reference dropped** — `responsesInputToMessages()` now synthesizes an assistant message with a matching `function_call` when a `function_call_output` has no prior matching call, preventing item_reference loss
|
|
8
|
+
- **Responses API: annotations missing** — Added `annotations: []` to all four `output_text` content items (streaming `.added`, `.done`, prefix, and non-streaming) for schema conformance
|
|
9
|
+
- **Responses API: item_id missing on reasoning events** — Added `item_id` to `reasoning_summary_part.added`, `reasoning_summary_part.done`, and `reasoning_summary_text.done` events
|
|
10
|
+
- **Responses API: web_search_call action missing type** — Changed `action: { query }` to `action: { type: "search", query }` in both streaming events and output prefix
|
|
11
|
+
- **Responses API: item_reference for text messages** — Extended item_reference handling to cover assistant text messages, not just function_call_output compensation
|
|
12
|
+
- **Responses API: multi-fco assistantCount inflation** — Fixed backward scan in `responsesInputToMessages()` to find and append to existing assistant messages with tool_calls instead of creating duplicates
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- **Debug logging across all LLM handlers** — Added `logger.debug("Fixture matched: ...")` on match and `logger.debug("No fixture matched...")` on no-match to: server.ts, responses.ts, messages.ts, gemini.ts, bedrock.ts, bedrock-converse.ts, cohere.ts, ollama.ts, embeddings.ts, images.ts, speech.ts, transcription.ts, video.ts
|
|
17
|
+
|
|
3
18
|
## 1.16.0
|
|
4
19
|
|
|
5
20
|
### Added
|
|
@@ -207,6 +207,8 @@ async function handleConverse(req, res, raw, modelId, fixtures, journal, default
|
|
|
207
207
|
completionReq._endpointType = "chat";
|
|
208
208
|
const testId = require_helpers.getTestId(req);
|
|
209
209
|
const fixture = require_router.matchFixture(fixtures, completionReq, journal.getFixtureMatchCountsForTest(testId), defaults.requestTransform);
|
|
210
|
+
if (fixture) logger.debug(`Fixture matched: ${JSON.stringify(fixture.match).slice(0, 120)}`);
|
|
211
|
+
else logger.debug(`No fixture matched for request`);
|
|
210
212
|
if (fixture) journal.incrementFixtureMatchCount(fixture, fixtures, testId);
|
|
211
213
|
if (require_chaos.applyChaos(res, fixture, defaults.chaos, req.headers, journal, {
|
|
212
214
|
method: req.method ?? "POST",
|
|
@@ -386,6 +388,8 @@ async function handleConverseStream(req, res, raw, modelId, fixtures, journal, d
|
|
|
386
388
|
completionReq._endpointType = "chat";
|
|
387
389
|
const testId = require_helpers.getTestId(req);
|
|
388
390
|
const fixture = require_router.matchFixture(fixtures, completionReq, journal.getFixtureMatchCountsForTest(testId), defaults.requestTransform);
|
|
391
|
+
if (fixture) logger.debug(`Fixture matched: ${JSON.stringify(fixture.match).slice(0, 120)}`);
|
|
392
|
+
else logger.debug(`No fixture matched for request`);
|
|
389
393
|
if (fixture) journal.incrementFixtureMatchCount(fixture, fixtures, testId);
|
|
390
394
|
if (require_chaos.applyChaos(res, fixture, defaults.chaos, req.headers, journal, {
|
|
391
395
|
method: req.method ?? "POST",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bedrock-converse.cjs","names":["generateToolUseId","flattenHeaders","getTestId","matchFixture","applyChaos","proxyAndRecord","isErrorResponse","isContentWithToolCallsResponse","extractOverrides","isTextResponse","isToolCallResponse","buildBedrockStreamContentWithToolCallsEvents","createInterruptionSignal","writeEventStream","buildBedrockStreamTextEvents","buildBedrockStreamToolCallEvents"],"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} 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\";\nimport {\n buildBedrockStreamTextEvents,\n buildBedrockStreamToolCallEvents,\n buildBedrockStreamContentWithToolCallsEvents,\n} from \"./bedrock.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\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\n// ─── Input conversion: Converse → ChatCompletionRequest ─────────────────────\n\nexport function converseToCompletionRequest(\n req: ConverseRequest,\n modelId: string,\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((b) => b.text !== undefined && !b.toolResult);\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)\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)\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 }\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,\n },\n }));\n }\n\n return {\n model: modelId,\n messages,\n stream: false,\n temperature: req.inferenceConfig?.temperature,\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 };\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 };\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 };\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 {\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\",\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);\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 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 defaults.registry,\n defaults.logger,\n )\n )\n return;\n\n if (!fixture) {\n if (defaults.record) {\n const proxied = await proxyAndRecord(\n req,\n res,\n completionReq,\n \"bedrock\",\n urlPath,\n fixtures,\n defaults,\n raw,\n );\n if (proxied) {\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 strictStatus = defaults.strict ? 503 : 404;\n const strictMessage = defaults.strict\n ? \"Strict mode: no fixture matched\"\n : \"No fixture matched\";\n if (defaults.strict) {\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: { status: strictStatus, fixture: null },\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 = fixture.response;\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 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 {\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\",\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);\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 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 defaults.registry,\n defaults.logger,\n )\n )\n return;\n\n if (!fixture) {\n if (defaults.record) {\n const proxied = await proxyAndRecord(\n req,\n res,\n completionReq,\n \"bedrock\",\n urlPath,\n fixtures,\n defaults,\n raw,\n );\n if (proxied) {\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 strictStatus = defaults.strict ? 503 : 404;\n const strictMessage = defaults.strict\n ? \"Strict mode: no fixture matched\"\n : \"No fixture matched\";\n if (defaults.strict) {\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: { status: strictStatus, fixture: null },\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 = fixture.response;\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 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.cjs","names":["generateToolUseId","flattenHeaders","getTestId","matchFixture","applyChaos","proxyAndRecord","isErrorResponse","isContentWithToolCallsResponse","extractOverrides","isTextResponse","isToolCallResponse","buildBedrockStreamContentWithToolCallsEvents","createInterruptionSignal","writeEventStream","buildBedrockStreamTextEvents","buildBedrockStreamToolCallEvents"],"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} 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\";\nimport {\n buildBedrockStreamTextEvents,\n buildBedrockStreamToolCallEvents,\n buildBedrockStreamContentWithToolCallsEvents,\n} from \"./bedrock.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\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\n// ─── Input conversion: Converse → ChatCompletionRequest ─────────────────────\n\nexport function converseToCompletionRequest(\n req: ConverseRequest,\n modelId: string,\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((b) => b.text !== undefined && !b.toolResult);\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)\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)\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 }\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,\n },\n }));\n }\n\n return {\n model: modelId,\n messages,\n stream: false,\n temperature: req.inferenceConfig?.temperature,\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 };\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 };\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 };\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 {\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\",\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);\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 defaults.registry,\n defaults.logger,\n )\n )\n return;\n\n if (!fixture) {\n if (defaults.record) {\n const proxied = await proxyAndRecord(\n req,\n res,\n completionReq,\n \"bedrock\",\n urlPath,\n fixtures,\n defaults,\n raw,\n );\n if (proxied) {\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 strictStatus = defaults.strict ? 503 : 404;\n const strictMessage = defaults.strict\n ? \"Strict mode: no fixture matched\"\n : \"No fixture matched\";\n if (defaults.strict) {\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: { status: strictStatus, fixture: null },\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 = fixture.response;\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 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 {\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\",\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);\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 defaults.registry,\n defaults.logger,\n )\n )\n return;\n\n if (!fixture) {\n if (defaults.record) {\n const proxied = await proxyAndRecord(\n req,\n res,\n completionReq,\n \"bedrock\",\n urlPath,\n fixtures,\n defaults,\n raw,\n );\n if (proxied) {\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 strictStatus = defaults.strict ? 503 : 404;\n const strictMessage = defaults.strict\n ? \"Strict mode: no fixture matched\"\n : \"No fixture matched\";\n if (defaults.strict) {\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: { status: strictStatus, fixture: null },\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 = fixture.response;\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 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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bedrock-converse.d.cts","names":[],"sources":["../src/bedrock-converse.ts"],"sourcesContent":[],"mappings":";;;;;;UA6CU,oBAAA,CAqB0B;EAAgB,IAAA,CAAA,EAAA,MAAA;EA6BpC,OAAA,CAAA,EAAA;IAA2B,SAAA,EAAA,MAAA;IACpC,IAAA,EAAA,MAAA;IAEJ,KAAA,EAAA,MAAA;EAAqB,CAAA;EAsMF,UAAA,CAAA,EAAA;IAAc,SAAA,EAAA,MAAA;IAC7B,OAAK,EAAA;MACA,IAAA,CAAA,EAAA,MAAA;IAGA,CAAA,EAAA;;;UA1PF,eAAA,CA6PmB;MAC1B,EAAA,MAAA,GAAA,WAAA;EAAO,OAAA,EA5PC,oBA4PD,EAAA;
|
|
1
|
+
{"version":3,"file":"bedrock-converse.d.cts","names":[],"sources":["../src/bedrock-converse.ts"],"sourcesContent":[],"mappings":";;;;;;UA6CU,oBAAA,CAqB0B;EAAgB,IAAA,CAAA,EAAA,MAAA;EA6BpC,OAAA,CAAA,EAAA;IAA2B,SAAA,EAAA,MAAA;IACpC,IAAA,EAAA,MAAA;IAEJ,KAAA,EAAA,MAAA;EAAqB,CAAA;EAsMF,UAAA,CAAA,EAAA;IAAc,SAAA,EAAA,MAAA;IAC7B,OAAK,EAAA;MACA,IAAA,CAAA,EAAA,MAAA;IAGA,CAAA,EAAA;;;UA1PF,eAAA,CA6PmB;MAC1B,EAAA,MAAA,GAAA,WAAA;EAAO,OAAA,EA5PC,oBA4PD,EAAA;AAwPV;UAjfU,gBAAA,CAifgC;MACnC,EAAA,MAAK;aACA,CAAA,EAAA,MAAA;aAGA,CAAA,EAAA,MAAA;;UAhfF,eAAA,CAkfE;UACiB,EAlfjB,eAkfiB,EAAA;QAC1B,CAAA,EAAA;IAAO,IAAA,EAAA,MAAA;;;;;;;;gBAhf0B;;;;iBA6BpB,2BAAA,MACT,mCAEJ;iBAsMmB,cAAA,MACf,IAAA,CAAK,sBACL,IAAA,CAAK,wDAGA,oBACD,mBACC,uCACY,IAAA,CAAK,0BAC1B;iBAwPmB,oBAAA,MACf,IAAA,CAAK,sBACL,IAAA,CAAK,wDAGA,oBACD,mBACC,uCACY,IAAA,CAAK,0BAC1B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bedrock-converse.d.ts","names":[],"sources":["../src/bedrock-converse.ts"],"sourcesContent":[],"mappings":";;;;;;UA6CU,oBAAA,CAqB0B;EAAgB,IAAA,CAAA,EAAA,MAAA;EA6BpC,OAAA,CAAA,EAAA;IAA2B,SAAA,EAAA,MAAA;IACpC,IAAA,EAAA,MAAA;IAEJ,KAAA,EAAA,MAAA;EAAqB,CAAA;EAsMF,UAAA,CAAA,EAAA;IAAc,SAAA,EAAA,MAAA;IAC7B,OAAK,EAAA;MACA,IAAA,CAAA,EAAA,MAAA;IAGA,CAAA,EAAA;;;UA1PF,eAAA,CA6PmB;MAC1B,EAAA,MAAA,GAAA,WAAA;EAAO,OAAA,EA5PC,oBA4PD,EAAA;
|
|
1
|
+
{"version":3,"file":"bedrock-converse.d.ts","names":[],"sources":["../src/bedrock-converse.ts"],"sourcesContent":[],"mappings":";;;;;;UA6CU,oBAAA,CAqB0B;EAAgB,IAAA,CAAA,EAAA,MAAA;EA6BpC,OAAA,CAAA,EAAA;IAA2B,SAAA,EAAA,MAAA;IACpC,IAAA,EAAA,MAAA;IAEJ,KAAA,EAAA,MAAA;EAAqB,CAAA;EAsMF,UAAA,CAAA,EAAA;IAAc,SAAA,EAAA,MAAA;IAC7B,OAAK,EAAA;MACA,IAAA,CAAA,EAAA,MAAA;IAGA,CAAA,EAAA;;;UA1PF,eAAA,CA6PmB;MAC1B,EAAA,MAAA,GAAA,WAAA;EAAO,OAAA,EA5PC,oBA4PD,EAAA;AAwPV;UAjfU,gBAAA,CAifgC;MACnC,EAAA,MAAK;aACA,CAAA,EAAA,MAAA;aAGA,CAAA,EAAA,MAAA;;UAhfF,eAAA,CAkfE;UACiB,EAlfjB,eAkfiB,EAAA;QAC1B,CAAA,EAAA;IAAO,IAAA,EAAA,MAAA;;;;;;;;gBAhf0B;;;;iBA6BpB,2BAAA,MACT,mCAEJ;iBAsMmB,cAAA,MACf,IAAA,CAAK,sBACL,IAAA,CAAK,wDAGA,oBACD,mBACC,uCACY,IAAA,CAAK,0BAC1B;iBAwPmB,oBAAA,MACf,IAAA,CAAK,sBACL,IAAA,CAAK,wDAGA,oBACD,mBACC,uCACY,IAAA,CAAK,0BAC1B"}
|
package/dist/bedrock-converse.js
CHANGED
|
@@ -207,6 +207,8 @@ async function handleConverse(req, res, raw, modelId, fixtures, journal, default
|
|
|
207
207
|
completionReq._endpointType = "chat";
|
|
208
208
|
const testId = getTestId(req);
|
|
209
209
|
const fixture = matchFixture(fixtures, completionReq, journal.getFixtureMatchCountsForTest(testId), defaults.requestTransform);
|
|
210
|
+
if (fixture) logger.debug(`Fixture matched: ${JSON.stringify(fixture.match).slice(0, 120)}`);
|
|
211
|
+
else logger.debug(`No fixture matched for request`);
|
|
210
212
|
if (fixture) journal.incrementFixtureMatchCount(fixture, fixtures, testId);
|
|
211
213
|
if (applyChaos(res, fixture, defaults.chaos, req.headers, journal, {
|
|
212
214
|
method: req.method ?? "POST",
|
|
@@ -386,6 +388,8 @@ async function handleConverseStream(req, res, raw, modelId, fixtures, journal, d
|
|
|
386
388
|
completionReq._endpointType = "chat";
|
|
387
389
|
const testId = getTestId(req);
|
|
388
390
|
const fixture = matchFixture(fixtures, completionReq, journal.getFixtureMatchCountsForTest(testId), defaults.requestTransform);
|
|
391
|
+
if (fixture) logger.debug(`Fixture matched: ${JSON.stringify(fixture.match).slice(0, 120)}`);
|
|
392
|
+
else logger.debug(`No fixture matched for request`);
|
|
389
393
|
if (fixture) journal.incrementFixtureMatchCount(fixture, fixtures, testId);
|
|
390
394
|
if (applyChaos(res, fixture, defaults.chaos, req.headers, journal, {
|
|
391
395
|
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} 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\";\nimport {\n buildBedrockStreamTextEvents,\n buildBedrockStreamToolCallEvents,\n buildBedrockStreamContentWithToolCallsEvents,\n} from \"./bedrock.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\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\n// ─── Input conversion: Converse → ChatCompletionRequest ─────────────────────\n\nexport function converseToCompletionRequest(\n req: ConverseRequest,\n modelId: string,\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((b) => b.text !== undefined && !b.toolResult);\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)\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)\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 }\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,\n },\n }));\n }\n\n return {\n model: modelId,\n messages,\n stream: false,\n temperature: req.inferenceConfig?.temperature,\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 };\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 };\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 };\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 {\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\",\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);\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 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 defaults.registry,\n defaults.logger,\n )\n )\n return;\n\n if (!fixture) {\n if (defaults.record) {\n const proxied = await proxyAndRecord(\n req,\n res,\n completionReq,\n \"bedrock\",\n urlPath,\n fixtures,\n defaults,\n raw,\n );\n if (proxied) {\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 strictStatus = defaults.strict ? 503 : 404;\n const strictMessage = defaults.strict\n ? \"Strict mode: no fixture matched\"\n : \"No fixture matched\";\n if (defaults.strict) {\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: { status: strictStatus, fixture: null },\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 = fixture.response;\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 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 {\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\",\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);\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 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 defaults.registry,\n defaults.logger,\n )\n )\n return;\n\n if (!fixture) {\n if (defaults.record) {\n const proxied = await proxyAndRecord(\n req,\n res,\n completionReq,\n \"bedrock\",\n urlPath,\n fixtures,\n defaults,\n raw,\n );\n if (proxied) {\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 strictStatus = defaults.strict ? 503 : 404;\n const strictMessage = defaults.strict\n ? \"Strict mode: no fixture matched\"\n : \"No fixture matched\";\n if (defaults.strict) {\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: { status: strictStatus, fixture: null },\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 = fixture.response;\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 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} 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\";\nimport {\n buildBedrockStreamTextEvents,\n buildBedrockStreamToolCallEvents,\n buildBedrockStreamContentWithToolCallsEvents,\n} from \"./bedrock.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\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\n// ─── Input conversion: Converse → ChatCompletionRequest ─────────────────────\n\nexport function converseToCompletionRequest(\n req: ConverseRequest,\n modelId: string,\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((b) => b.text !== undefined && !b.toolResult);\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)\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)\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 }\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,\n },\n }));\n }\n\n return {\n model: modelId,\n messages,\n stream: false,\n temperature: req.inferenceConfig?.temperature,\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 };\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 };\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 };\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 {\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\",\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);\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 defaults.registry,\n defaults.logger,\n )\n )\n return;\n\n if (!fixture) {\n if (defaults.record) {\n const proxied = await proxyAndRecord(\n req,\n res,\n completionReq,\n \"bedrock\",\n urlPath,\n fixtures,\n defaults,\n raw,\n );\n if (proxied) {\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 strictStatus = defaults.strict ? 503 : 404;\n const strictMessage = defaults.strict\n ? \"Strict mode: no fixture matched\"\n : \"No fixture matched\";\n if (defaults.strict) {\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: { status: strictStatus, fixture: null },\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 = fixture.response;\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 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 {\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\",\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);\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 defaults.registry,\n defaults.logger,\n )\n )\n return;\n\n if (!fixture) {\n if (defaults.record) {\n const proxied = await proxyAndRecord(\n req,\n res,\n completionReq,\n \"bedrock\",\n urlPath,\n fixtures,\n defaults,\n raw,\n );\n if (proxied) {\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 strictStatus = defaults.strict ? 503 : 404;\n const strictMessage = defaults.strict\n ? \"Strict mode: no fixture matched\"\n : \"No fixture matched\";\n if (defaults.strict) {\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: { status: strictStatus, fixture: null },\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 = fixture.response;\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 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
|
@@ -197,6 +197,8 @@ async function handleBedrock(req, res, raw, modelId, fixtures, journal, defaults
|
|
|
197
197
|
completionReq._endpointType = "chat";
|
|
198
198
|
const testId = require_helpers.getTestId(req);
|
|
199
199
|
const fixture = require_router.matchFixture(fixtures, completionReq, journal.getFixtureMatchCountsForTest(testId), defaults.requestTransform);
|
|
200
|
+
if (fixture) logger.debug(`Fixture matched: ${JSON.stringify(fixture.match).slice(0, 120)}`);
|
|
201
|
+
else logger.debug(`No fixture matched for request`);
|
|
200
202
|
if (fixture) journal.incrementFixtureMatchCount(fixture, fixtures, testId);
|
|
201
203
|
if (require_chaos.applyChaos(res, fixture, defaults.chaos, req.headers, journal, {
|
|
202
204
|
method: req.method ?? "POST",
|
|
@@ -632,6 +634,8 @@ async function handleBedrockStream(req, res, raw, modelId, fixtures, journal, de
|
|
|
632
634
|
completionReq._endpointType = "chat";
|
|
633
635
|
const testId = require_helpers.getTestId(req);
|
|
634
636
|
const fixture = require_router.matchFixture(fixtures, completionReq, journal.getFixtureMatchCountsForTest(testId), defaults.requestTransform);
|
|
637
|
+
if (fixture) logger.debug(`Fixture matched: ${JSON.stringify(fixture.match).slice(0, 120)}`);
|
|
638
|
+
else logger.debug(`No fixture matched for request`);
|
|
635
639
|
if (fixture) journal.incrementFixtureMatchCount(fixture, fixtures, testId);
|
|
636
640
|
if (require_chaos.applyChaos(res, fixture, defaults.chaos, req.headers, journal, {
|
|
637
641
|
method: req.method ?? "POST",
|