@copilotkit/aimock 1.8.0 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +19 -17
- package/dist/a2a-types.d.ts.map +1 -1
- package/dist/bedrock-converse.cjs +6 -4
- 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 +7 -5
- package/dist/bedrock-converse.js.map +1 -1
- package/dist/bedrock.cjs +6 -4
- 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 +7 -5
- package/dist/bedrock.js.map +1 -1
- package/dist/cli.cjs +10 -4
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +10 -4
- package/dist/cli.js.map +1 -1
- package/dist/cohere.cjs +3 -2
- package/dist/cohere.cjs.map +1 -1
- package/dist/cohere.d.cts.map +1 -1
- package/dist/cohere.d.ts.map +1 -1
- package/dist/cohere.js +4 -3
- package/dist/cohere.js.map +1 -1
- package/dist/embeddings.cjs +3 -2
- package/dist/embeddings.cjs.map +1 -1
- package/dist/embeddings.d.cts.map +1 -1
- package/dist/embeddings.d.ts.map +1 -1
- package/dist/embeddings.js +4 -3
- package/dist/embeddings.js.map +1 -1
- package/dist/gemini.cjs +105 -30
- package/dist/gemini.cjs.map +1 -1
- package/dist/gemini.d.cts.map +1 -1
- package/dist/gemini.d.ts.map +1 -1
- package/dist/gemini.js +106 -31
- package/dist/gemini.js.map +1 -1
- package/dist/helpers.cjs +150 -14
- package/dist/helpers.cjs.map +1 -1
- package/dist/helpers.d.cts.map +1 -1
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +147 -15
- package/dist/helpers.js.map +1 -1
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/journal.cjs +26 -9
- package/dist/journal.cjs.map +1 -1
- package/dist/journal.d.cts +10 -5
- package/dist/journal.d.cts.map +1 -1
- package/dist/journal.d.ts +10 -5
- package/dist/journal.d.ts.map +1 -1
- package/dist/journal.js +26 -10
- package/dist/journal.js.map +1 -1
- package/dist/llmock.cjs +2 -2
- package/dist/llmock.cjs.map +1 -1
- package/dist/llmock.d.cts +1 -1
- package/dist/llmock.d.ts +1 -1
- package/dist/llmock.js +2 -2
- package/dist/llmock.js.map +1 -1
- package/dist/messages.cjs +192 -2
- package/dist/messages.cjs.map +1 -1
- package/dist/messages.d.cts.map +1 -1
- package/dist/messages.d.ts.map +1 -1
- package/dist/messages.js +193 -3
- package/dist/messages.js.map +1 -1
- package/dist/ollama.cjs +6 -4
- 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 +7 -5
- package/dist/ollama.js.map +1 -1
- package/dist/recorder.cjs +23 -21
- package/dist/recorder.cjs.map +1 -1
- package/dist/recorder.js +23 -21
- package/dist/recorder.js.map +1 -1
- package/dist/responses.cjs +250 -126
- 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 +251 -127
- package/dist/responses.js.map +1 -1
- package/dist/server.cjs +42 -5
- 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 +43 -6
- package/dist/server.js.map +1 -1
- package/dist/stream-collapse.cjs +48 -40
- package/dist/stream-collapse.cjs.map +1 -1
- package/dist/stream-collapse.d.cts.map +1 -1
- package/dist/stream-collapse.d.ts.map +1 -1
- package/dist/stream-collapse.js +48 -40
- package/dist/stream-collapse.js.map +1 -1
- package/dist/types.d.cts +11 -1
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.ts +11 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/vector-types.d.ts.map +1 -1
- package/dist/ws-gemini-live.cjs +4 -2
- package/dist/ws-gemini-live.cjs.map +1 -1
- package/dist/ws-gemini-live.d.cts +1 -0
- package/dist/ws-gemini-live.d.ts +1 -0
- package/dist/ws-gemini-live.js +4 -2
- package/dist/ws-gemini-live.js.map +1 -1
- package/dist/ws-realtime.cjs +4 -2
- package/dist/ws-realtime.cjs.map +1 -1
- package/dist/ws-realtime.d.cts +1 -0
- package/dist/ws-realtime.d.ts +1 -0
- package/dist/ws-realtime.js +4 -2
- package/dist/ws-realtime.js.map +1 -1
- package/dist/ws-responses.cjs +4 -2
- package/dist/ws-responses.cjs.map +1 -1
- package/dist/ws-responses.d.cts +1 -0
- package/dist/ws-responses.d.ts +1 -0
- package/dist/ws-responses.js +4 -2
- package/dist/ws-responses.js.map +1 -1
- package/package.json +1 -1
package/dist/bedrock.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bedrock.cjs","names":["generateToolUseId","generateMessageId","flattenHeaders","matchFixture","applyChaos","proxyAndRecord","isErrorResponse","isTextResponse","isToolCallResponse","createInterruptionSignal","writeEventStream"],"sources":["../src/bedrock.ts"],"sourcesContent":["/**\n * AWS Bedrock Claude endpoint support — invoke and invoke-with-response-stream.\n *\n * Handles four Bedrock endpoint families (split across two modules):\n *\n * This file (bedrock.ts):\n * - POST /model/{modelId}/invoke — non-streaming invoke\n * - POST /model/{modelId}/invoke-with-response-stream — binary EventStream streaming\n *\n * bedrock-converse.ts:\n * - POST /model/{modelId}/converse — Converse API (non-streaming)\n * - POST /model/{modelId}/converse-stream — Converse API (EventStream streaming)\n *\n * Translates incoming Bedrock Claude format into the ChatCompletionRequest\n * format used by the fixture router, and converts fixture responses back into\n * the appropriate Bedrock response format (JSON for invoke, AWS Event Stream\n * binary encoding for streaming).\n */\n\nimport type * as http from \"node:http\";\nimport type {\n ChatCompletionRequest,\n ChatMessage,\n Fixture,\n HandlerDefaults,\n ToolCall,\n ToolDefinition,\n} from \"./types.js\";\nimport {\n generateMessageId,\n generateToolUseId,\n isTextResponse,\n isToolCallResponse,\n isErrorResponse,\n flattenHeaders,\n} from \"./helpers.js\";\nimport { matchFixture } from \"./router.js\";\nimport { writeErrorResponse } from \"./sse-writer.js\";\nimport { writeEventStream } from \"./aws-event-stream.js\";\nimport { createInterruptionSignal } from \"./interruption.js\";\nimport type { Journal } from \"./journal.js\";\nimport type { Logger } from \"./logger.js\";\nimport { applyChaos } from \"./chaos.js\";\nimport { proxyAndRecord } from \"./recorder.js\";\n\n// ─── Bedrock Claude request types ────────────────────────────────────────────\n\ninterface BedrockContentBlock {\n type: \"text\" | \"tool_use\" | \"tool_result\" | \"image\" | \"document\";\n text?: string;\n id?: string;\n name?: string;\n input?: unknown;\n tool_use_id?: string;\n content?: string | BedrockContentBlock[];\n is_error?: boolean;\n}\n\ninterface BedrockMessage {\n role: \"user\" | \"assistant\";\n content: string | BedrockContentBlock[];\n}\n\ninterface BedrockToolDef {\n name: string;\n description?: string;\n input_schema?: object;\n}\n\ninterface BedrockRequest {\n anthropic_version?: string;\n messages: BedrockMessage[];\n system?: string | BedrockContentBlock[];\n tools?: BedrockToolDef[];\n tool_choice?: unknown;\n max_tokens: number;\n temperature?: number;\n [key: string]: unknown;\n}\n\n// ─── Input conversion: Bedrock → ChatCompletionRequest ──────────────────────\n\nfunction extractTextContent(content: string | BedrockContentBlock[]): string {\n if (typeof content === \"string\") return content;\n return content\n .filter((b) => b.type === \"text\")\n .map((b) => b.text ?? \"\")\n .join(\"\");\n}\n\nexport function bedrockToCompletionRequest(\n req: BedrockRequest,\n modelId: string,\n): ChatCompletionRequest {\n const messages: ChatMessage[] = [];\n\n // system field → system message\n if (req.system) {\n const systemText =\n typeof req.system === \"string\"\n ? req.system\n : req.system\n .filter((b) => b.type === \"text\")\n .map((b) => b.text ?? \"\")\n .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 tool_result blocks\n if (typeof msg.content !== \"string\" && Array.isArray(msg.content)) {\n const toolResults = msg.content.filter((b) => b.type === \"tool_result\");\n const textBlocks = msg.content.filter((b) => b.type === \"text\");\n\n if (toolResults.length > 0) {\n for (const tr of toolResults) {\n const resultContent =\n typeof tr.content === \"string\"\n ? tr.content\n : Array.isArray(tr.content)\n ? tr.content\n .filter((b) => b.type === \"text\")\n .map((b) => b.text ?? \"\")\n .join(\"\")\n : \"\";\n messages.push({\n role: \"tool\",\n content: resultContent,\n tool_call_id: tr.tool_use_id,\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 messages.push({\n role: \"user\",\n content: extractTextContent(msg.content),\n });\n } else if (msg.role === \"assistant\") {\n if (typeof msg.content === \"string\") {\n messages.push({ role: \"assistant\", content: msg.content });\n } else if (Array.isArray(msg.content)) {\n const toolUseBlocks = msg.content.filter((b) => b.type === \"tool_use\");\n const textContent = extractTextContent(msg.content);\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.id ?? generateToolUseId(),\n type: \"function\" as const,\n function: {\n name: b.name ?? \"\",\n arguments: typeof b.input === \"string\" ? b.input : JSON.stringify(b.input ?? {}),\n },\n })),\n });\n } else {\n messages.push({ role: \"assistant\", content: textContent || null });\n }\n } else {\n messages.push({ role: \"assistant\", content: null });\n }\n }\n }\n\n // Convert tools\n let tools: ToolDefinition[] | undefined;\n if (req.tools && req.tools.length > 0) {\n tools = req.tools.map((t) => ({\n type: \"function\" as const,\n function: {\n name: t.name,\n description: t.description,\n parameters: t.input_schema,\n },\n }));\n }\n\n return {\n model: modelId,\n messages,\n stream: false,\n temperature: req.temperature,\n tools,\n };\n}\n\n// ─── Response builders ──────────────────────────────────────────────────────\n\nfunction buildBedrockTextResponse(content: string, model: string, reasoning?: string): object {\n const contentBlocks: object[] = [];\n if (reasoning) {\n contentBlocks.push({ type: \"thinking\", thinking: reasoning });\n }\n contentBlocks.push({ type: \"text\", text: content });\n\n return {\n id: generateMessageId(),\n type: \"message\",\n role: \"assistant\",\n content: contentBlocks,\n model,\n stop_reason: \"end_turn\",\n stop_sequence: null,\n usage: { input_tokens: 0, output_tokens: 0 },\n };\n}\n\nfunction buildBedrockToolCallResponse(\n toolCalls: ToolCall[],\n model: string,\n logger: Logger,\n): object {\n return {\n id: generateMessageId(),\n type: \"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 type: \"tool_use\",\n id: tc.id || generateToolUseId(),\n name: tc.name,\n input: argsObj,\n };\n }),\n model,\n stop_reason: \"tool_use\",\n stop_sequence: null,\n usage: { input_tokens: 0, output_tokens: 0 },\n };\n}\n\n// ─── Request handler ────────────────────────────────────────────────────────\n\nexport async function handleBedrock(\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}/invoke`;\n\n let bedrockReq: BedrockRequest;\n try {\n bedrockReq = JSON.parse(raw) as BedrockRequest;\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 (!bedrockReq.messages || !Array.isArray(bedrockReq.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 // Convert to ChatCompletionRequest for fixture matching\n const completionReq = bedrockToCompletionRequest(bedrockReq, modelId);\n\n const fixture = matchFixture(\n fixtures,\n completionReq,\n journal.fixtureMatchCounts,\n defaults.requestTransform,\n );\n\n if (fixture) {\n journal.incrementFixtureMatchCount(fixture, fixtures);\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 },\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 // Anthropic-style error format (Bedrock uses Claude): { type: \"error\", error: { type, message } }\n const anthropicError = {\n type: \"error\",\n error: {\n type: response.error.type ?? \"api_error\",\n message: response.error.message,\n },\n };\n writeErrorResponse(res, status, JSON.stringify(anthropicError));\n return;\n }\n\n // Text response\n if (isTextResponse(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 = buildBedrockTextResponse(\n response.content,\n completionReq.model,\n response.reasoning,\n );\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 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 = buildBedrockToolCallResponse(response.toolCalls, completionReq.model, logger);\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\n// ─── Streaming event builders ───────────────────────────────────────────────\n\nexport function buildBedrockStreamTextEvents(\n content: string,\n chunkSize: number,\n reasoning?: string,\n): Array<{ eventType: string; payload: object }> {\n const events: Array<{ eventType: string; payload: object }> = [];\n\n events.push({\n eventType: \"messageStart\",\n payload: { role: \"assistant\" },\n });\n\n // Thinking block (emitted before text when reasoning is present)\n if (reasoning) {\n const blockIndex = 0;\n events.push({\n eventType: \"contentBlockStart\",\n payload: { contentBlockIndex: blockIndex, start: { type: \"thinking\" } },\n });\n\n for (let i = 0; i < reasoning.length; i += chunkSize) {\n const slice = reasoning.slice(i, i + chunkSize);\n events.push({\n eventType: \"contentBlockDelta\",\n payload: {\n contentBlockIndex: blockIndex,\n delta: { type: \"thinking_delta\", thinking: slice },\n },\n });\n }\n\n events.push({\n eventType: \"contentBlockStop\",\n payload: { contentBlockIndex: blockIndex },\n });\n }\n\n // Text block\n const textBlockIndex = reasoning ? 1 : 0;\n\n events.push({\n eventType: \"contentBlockStart\",\n payload: { contentBlockIndex: textBlockIndex, start: {} },\n });\n\n for (let i = 0; i < content.length; i += chunkSize) {\n const slice = content.slice(i, i + chunkSize);\n events.push({\n eventType: \"contentBlockDelta\",\n payload: {\n contentBlockIndex: textBlockIndex,\n delta: { type: \"text_delta\", text: slice },\n },\n });\n }\n\n events.push({\n eventType: \"contentBlockStop\",\n payload: { contentBlockIndex: textBlockIndex },\n });\n\n events.push({\n eventType: \"messageStop\",\n payload: { stopReason: \"end_turn\" },\n });\n\n return events;\n}\n\nexport function buildBedrockStreamToolCallEvents(\n toolCalls: ToolCall[],\n chunkSize: number,\n logger: Logger,\n): Array<{ eventType: string; payload: object }> {\n const events: Array<{ eventType: string; payload: object }> = [];\n\n events.push({\n eventType: \"messageStart\",\n payload: { role: \"assistant\" },\n });\n\n for (let tcIdx = 0; tcIdx < toolCalls.length; tcIdx++) {\n const tc = toolCalls[tcIdx];\n const toolUseId = tc.id || generateToolUseId();\n\n events.push({\n eventType: \"contentBlockStart\",\n payload: {\n contentBlockIndex: tcIdx,\n start: {\n toolUse: { toolUseId, name: tc.name },\n },\n },\n });\n\n let argsStr: string;\n try {\n const parsed = JSON.parse(tc.arguments || \"{}\");\n argsStr = JSON.stringify(parsed);\n } catch {\n logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n );\n argsStr = \"{}\";\n }\n\n for (let i = 0; i < argsStr.length; i += chunkSize) {\n const slice = argsStr.slice(i, i + chunkSize);\n events.push({\n eventType: \"contentBlockDelta\",\n payload: {\n contentBlockIndex: tcIdx,\n delta: { type: \"input_json_delta\", inputJSON: slice },\n },\n });\n }\n\n events.push({\n eventType: \"contentBlockStop\",\n payload: { contentBlockIndex: tcIdx },\n });\n }\n\n events.push({\n eventType: \"messageStop\",\n payload: { stopReason: \"tool_use\" },\n });\n\n return events;\n}\n\n// ─── Streaming request handler ──────────────────────────────────────────────\n\nexport async function handleBedrockStream(\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}/invoke-with-response-stream`;\n\n let bedrockReq: BedrockRequest;\n try {\n bedrockReq = JSON.parse(raw) as BedrockRequest;\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 (!bedrockReq.messages || !Array.isArray(bedrockReq.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 = bedrockToCompletionRequest(bedrockReq, modelId);\n\n const fixture = matchFixture(\n fixtures,\n completionReq,\n journal.fixtureMatchCounts,\n defaults.requestTransform,\n );\n\n if (fixture) {\n journal.incrementFixtureMatchCount(fixture, fixtures);\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 },\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 writeErrorResponse(res, status, JSON.stringify(response));\n return;\n }\n\n // Text response — stream as Event Stream\n if (isTextResponse(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(response.content, chunkSize, response.reasoning);\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 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(response.toolCalls, chunkSize, logger);\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.cjs","names":["generateToolUseId","generateMessageId","flattenHeaders","getTestId","matchFixture","applyChaos","proxyAndRecord","isErrorResponse","isTextResponse","isToolCallResponse","createInterruptionSignal","writeEventStream"],"sources":["../src/bedrock.ts"],"sourcesContent":["/**\n * AWS Bedrock Claude endpoint support — invoke and invoke-with-response-stream.\n *\n * Handles four Bedrock endpoint families (split across two modules):\n *\n * This file (bedrock.ts):\n * - POST /model/{modelId}/invoke — non-streaming invoke\n * - POST /model/{modelId}/invoke-with-response-stream — binary EventStream streaming\n *\n * bedrock-converse.ts:\n * - POST /model/{modelId}/converse — Converse API (non-streaming)\n * - POST /model/{modelId}/converse-stream — Converse API (EventStream streaming)\n *\n * Translates incoming Bedrock Claude format into the ChatCompletionRequest\n * format used by the fixture router, and converts fixture responses back into\n * the appropriate Bedrock response format (JSON for invoke, AWS Event Stream\n * binary encoding for streaming).\n */\n\nimport type * as http from \"node:http\";\nimport type {\n ChatCompletionRequest,\n ChatMessage,\n Fixture,\n HandlerDefaults,\n ToolCall,\n ToolDefinition,\n} from \"./types.js\";\nimport {\n generateMessageId,\n generateToolUseId,\n isTextResponse,\n isToolCallResponse,\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\";\n\n// ─── Bedrock Claude request types ────────────────────────────────────────────\n\ninterface BedrockContentBlock {\n type: \"text\" | \"tool_use\" | \"tool_result\" | \"image\" | \"document\";\n text?: string;\n id?: string;\n name?: string;\n input?: unknown;\n tool_use_id?: string;\n content?: string | BedrockContentBlock[];\n is_error?: boolean;\n}\n\ninterface BedrockMessage {\n role: \"user\" | \"assistant\";\n content: string | BedrockContentBlock[];\n}\n\ninterface BedrockToolDef {\n name: string;\n description?: string;\n input_schema?: object;\n}\n\ninterface BedrockRequest {\n anthropic_version?: string;\n messages: BedrockMessage[];\n system?: string | BedrockContentBlock[];\n tools?: BedrockToolDef[];\n tool_choice?: unknown;\n max_tokens: number;\n temperature?: number;\n [key: string]: unknown;\n}\n\n// ─── Input conversion: Bedrock → ChatCompletionRequest ──────────────────────\n\nfunction extractTextContent(content: string | BedrockContentBlock[]): string {\n if (typeof content === \"string\") return content;\n return content\n .filter((b) => b.type === \"text\")\n .map((b) => b.text ?? \"\")\n .join(\"\");\n}\n\nexport function bedrockToCompletionRequest(\n req: BedrockRequest,\n modelId: string,\n): ChatCompletionRequest {\n const messages: ChatMessage[] = [];\n\n // system field → system message\n if (req.system) {\n const systemText =\n typeof req.system === \"string\"\n ? req.system\n : req.system\n .filter((b) => b.type === \"text\")\n .map((b) => b.text ?? \"\")\n .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 tool_result blocks\n if (typeof msg.content !== \"string\" && Array.isArray(msg.content)) {\n const toolResults = msg.content.filter((b) => b.type === \"tool_result\");\n const textBlocks = msg.content.filter((b) => b.type === \"text\");\n\n if (toolResults.length > 0) {\n for (const tr of toolResults) {\n const resultContent =\n typeof tr.content === \"string\"\n ? tr.content\n : Array.isArray(tr.content)\n ? tr.content\n .filter((b) => b.type === \"text\")\n .map((b) => b.text ?? \"\")\n .join(\"\")\n : \"\";\n messages.push({\n role: \"tool\",\n content: resultContent,\n tool_call_id: tr.tool_use_id,\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 messages.push({\n role: \"user\",\n content: extractTextContent(msg.content),\n });\n } else if (msg.role === \"assistant\") {\n if (typeof msg.content === \"string\") {\n messages.push({ role: \"assistant\", content: msg.content });\n } else if (Array.isArray(msg.content)) {\n const toolUseBlocks = msg.content.filter((b) => b.type === \"tool_use\");\n const textContent = extractTextContent(msg.content);\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.id ?? generateToolUseId(),\n type: \"function\" as const,\n function: {\n name: b.name ?? \"\",\n arguments: typeof b.input === \"string\" ? b.input : JSON.stringify(b.input ?? {}),\n },\n })),\n });\n } else {\n messages.push({ role: \"assistant\", content: textContent || null });\n }\n } else {\n messages.push({ role: \"assistant\", content: null });\n }\n }\n }\n\n // Convert tools\n let tools: ToolDefinition[] | undefined;\n if (req.tools && req.tools.length > 0) {\n tools = req.tools.map((t) => ({\n type: \"function\" as const,\n function: {\n name: t.name,\n description: t.description,\n parameters: t.input_schema,\n },\n }));\n }\n\n return {\n model: modelId,\n messages,\n stream: false,\n temperature: req.temperature,\n tools,\n };\n}\n\n// ─── Response builders ──────────────────────────────────────────────────────\n\nfunction buildBedrockTextResponse(content: string, model: string, reasoning?: string): object {\n const contentBlocks: object[] = [];\n if (reasoning) {\n contentBlocks.push({ type: \"thinking\", thinking: reasoning });\n }\n contentBlocks.push({ type: \"text\", text: content });\n\n return {\n id: generateMessageId(),\n type: \"message\",\n role: \"assistant\",\n content: contentBlocks,\n model,\n stop_reason: \"end_turn\",\n stop_sequence: null,\n usage: { input_tokens: 0, output_tokens: 0 },\n };\n}\n\nfunction buildBedrockToolCallResponse(\n toolCalls: ToolCall[],\n model: string,\n logger: Logger,\n): object {\n return {\n id: generateMessageId(),\n type: \"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 type: \"tool_use\",\n id: tc.id || generateToolUseId(),\n name: tc.name,\n input: argsObj,\n };\n }),\n model,\n stop_reason: \"tool_use\",\n stop_sequence: null,\n usage: { input_tokens: 0, output_tokens: 0 },\n };\n}\n\n// ─── Request handler ────────────────────────────────────────────────────────\n\nexport async function handleBedrock(\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}/invoke`;\n\n let bedrockReq: BedrockRequest;\n try {\n bedrockReq = JSON.parse(raw) as BedrockRequest;\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 (!bedrockReq.messages || !Array.isArray(bedrockReq.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 // Convert to ChatCompletionRequest for fixture matching\n const completionReq = bedrockToCompletionRequest(bedrockReq, modelId);\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 },\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 // Anthropic-style error format (Bedrock uses Claude): { type: \"error\", error: { type, message } }\n const anthropicError = {\n type: \"error\",\n error: {\n type: response.error.type ?? \"api_error\",\n message: response.error.message,\n },\n };\n writeErrorResponse(res, status, JSON.stringify(anthropicError));\n return;\n }\n\n // Text response\n if (isTextResponse(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 = buildBedrockTextResponse(\n response.content,\n completionReq.model,\n response.reasoning,\n );\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 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 = buildBedrockToolCallResponse(response.toolCalls, completionReq.model, logger);\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\n// ─── Streaming event builders ───────────────────────────────────────────────\n\nexport function buildBedrockStreamTextEvents(\n content: string,\n chunkSize: number,\n reasoning?: string,\n): Array<{ eventType: string; payload: object }> {\n const events: Array<{ eventType: string; payload: object }> = [];\n\n events.push({\n eventType: \"messageStart\",\n payload: { role: \"assistant\" },\n });\n\n // Thinking block (emitted before text when reasoning is present)\n if (reasoning) {\n const blockIndex = 0;\n events.push({\n eventType: \"contentBlockStart\",\n payload: { contentBlockIndex: blockIndex, start: { type: \"thinking\" } },\n });\n\n for (let i = 0; i < reasoning.length; i += chunkSize) {\n const slice = reasoning.slice(i, i + chunkSize);\n events.push({\n eventType: \"contentBlockDelta\",\n payload: {\n contentBlockIndex: blockIndex,\n delta: { type: \"thinking_delta\", thinking: slice },\n },\n });\n }\n\n events.push({\n eventType: \"contentBlockStop\",\n payload: { contentBlockIndex: blockIndex },\n });\n }\n\n // Text block\n const textBlockIndex = reasoning ? 1 : 0;\n\n events.push({\n eventType: \"contentBlockStart\",\n payload: { contentBlockIndex: textBlockIndex, start: {} },\n });\n\n for (let i = 0; i < content.length; i += chunkSize) {\n const slice = content.slice(i, i + chunkSize);\n events.push({\n eventType: \"contentBlockDelta\",\n payload: {\n contentBlockIndex: textBlockIndex,\n delta: { type: \"text_delta\", text: slice },\n },\n });\n }\n\n events.push({\n eventType: \"contentBlockStop\",\n payload: { contentBlockIndex: textBlockIndex },\n });\n\n events.push({\n eventType: \"messageStop\",\n payload: { stopReason: \"end_turn\" },\n });\n\n return events;\n}\n\nexport function buildBedrockStreamToolCallEvents(\n toolCalls: ToolCall[],\n chunkSize: number,\n logger: Logger,\n): Array<{ eventType: string; payload: object }> {\n const events: Array<{ eventType: string; payload: object }> = [];\n\n events.push({\n eventType: \"messageStart\",\n payload: { role: \"assistant\" },\n });\n\n for (let tcIdx = 0; tcIdx < toolCalls.length; tcIdx++) {\n const tc = toolCalls[tcIdx];\n const toolUseId = tc.id || generateToolUseId();\n\n events.push({\n eventType: \"contentBlockStart\",\n payload: {\n contentBlockIndex: tcIdx,\n start: {\n toolUse: { toolUseId, name: tc.name },\n },\n },\n });\n\n let argsStr: string;\n try {\n const parsed = JSON.parse(tc.arguments || \"{}\");\n argsStr = JSON.stringify(parsed);\n } catch {\n logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n );\n argsStr = \"{}\";\n }\n\n for (let i = 0; i < argsStr.length; i += chunkSize) {\n const slice = argsStr.slice(i, i + chunkSize);\n events.push({\n eventType: \"contentBlockDelta\",\n payload: {\n contentBlockIndex: tcIdx,\n delta: { type: \"input_json_delta\", inputJSON: slice },\n },\n });\n }\n\n events.push({\n eventType: \"contentBlockStop\",\n payload: { contentBlockIndex: tcIdx },\n });\n }\n\n events.push({\n eventType: \"messageStop\",\n payload: { stopReason: \"tool_use\" },\n });\n\n return events;\n}\n\n// ─── Streaming request handler ──────────────────────────────────────────────\n\nexport async function handleBedrockStream(\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}/invoke-with-response-stream`;\n\n let bedrockReq: BedrockRequest;\n try {\n bedrockReq = JSON.parse(raw) as BedrockRequest;\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 (!bedrockReq.messages || !Array.isArray(bedrockReq.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 = bedrockToCompletionRequest(bedrockReq, modelId);\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 },\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 writeErrorResponse(res, status, JSON.stringify(response));\n return;\n }\n\n // Text response — stream as Event Stream\n if (isTextResponse(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(response.content, chunkSize, response.reasoning);\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 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(response.toolCalls, chunkSize, logger);\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.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bedrock.d.cts","names":[],"sources":["../src/bedrock.ts"],"sourcesContent":[],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"bedrock.d.cts","names":[],"sources":["../src/bedrock.ts"],"sourcesContent":[],"mappings":";;;;;;UAgDU,mBAAA,CAiNE;MAGA,EAAA,MAAA,GAAA,UAAA,GAAA,aAAA,GAAA,OAAA,GAAA,UAAA;MACD,CAAA,EAAA,MAAA;KACC,EAAA,MAAA;MACY,CAAA,EAAA,MAAK;OAC1B,CAAA,EAAA,OAAA;EAAO,WAAA,CAAA,EAAA,MAAA;EA4VY,OAAA,CAAA,EAAA,MAAA,GA7iBD,mBA6iBoB,EAAA;EAAA,QAAA,CAAA,EAAA,OAAA;;UAziB/B,cAAA,CA2iBE;MAGA,EAAA,MAAA,GAAA,WAAA;SACD,EAAA,MAAA,GA7iBS,mBA6iBT,EAAA;;UA1iBD,cAAA,CA4iBmB;MAC1B,EAAA,MAAA;EAAO,WAAA,CAAA,EAAA,MAAA;;;UAviBA,cAAA;;YAEE;oBACQ;UACV;;;;;;iBAiBM,0BAAA,MACT,kCAEJ;iBAiKmB,aAAA,MACf,IAAA,CAAK,sBACL,IAAA,CAAK,wDAGA,oBACD,mBACC,uCACY,IAAA,CAAK,0BAC1B;iBA4VmB,mBAAA,MACf,IAAA,CAAK,sBACL,IAAA,CAAK,wDAGA,oBACD,mBACC,uCACY,IAAA,CAAK,0BAC1B"}
|
package/dist/bedrock.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bedrock.d.ts","names":[],"sources":["../src/bedrock.ts"],"sourcesContent":[],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"bedrock.d.ts","names":[],"sources":["../src/bedrock.ts"],"sourcesContent":[],"mappings":";;;;;;UAgDU,mBAAA,CAiNE;MAGA,EAAA,MAAA,GAAA,UAAA,GAAA,aAAA,GAAA,OAAA,GAAA,UAAA;MACD,CAAA,EAAA,MAAA;KACC,EAAA,MAAA;MACY,CAAA,EAAA,MAAK;OAC1B,CAAA,EAAA,OAAA;EAAO,WAAA,CAAA,EAAA,MAAA;EA4VY,OAAA,CAAA,EAAA,MAAA,GA7iBD,mBA6iBoB,EAAA;EAAA,QAAA,CAAA,EAAA,OAAA;;UAziB/B,cAAA,CA2iBE;MAGA,EAAA,MAAA,GAAA,WAAA;SACD,EAAA,MAAA,GA7iBS,mBA6iBT,EAAA;;UA1iBD,cAAA,CA4iBmB;MAC1B,EAAA,MAAA;EAAO,WAAA,CAAA,EAAA,MAAA;;;UAviBA,cAAA;;YAEE;oBACQ;UACV;;;;;;iBAiBM,0BAAA,MACT,kCAEJ;iBAiKmB,aAAA,MACf,IAAA,CAAK,sBACL,IAAA,CAAK,wDAGA,oBACD,mBACC,uCACY,IAAA,CAAK,0BAC1B;iBA4VmB,mBAAA,MACf,IAAA,CAAK,sBACL,IAAA,CAAK,wDAGA,oBACD,mBACC,uCACY,IAAA,CAAK,0BAC1B"}
|
package/dist/bedrock.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { flattenHeaders, generateMessageId, generateToolUseId, isErrorResponse, isTextResponse, isToolCallResponse } from "./helpers.js";
|
|
1
|
+
import { flattenHeaders, generateMessageId, generateToolUseId, getTestId, isErrorResponse, isTextResponse, isToolCallResponse } from "./helpers.js";
|
|
2
2
|
import { matchFixture } from "./router.js";
|
|
3
3
|
import { writeErrorResponse } from "./sse-writer.js";
|
|
4
4
|
import { createInterruptionSignal } from "./interruption.js";
|
|
@@ -183,8 +183,9 @@ async function handleBedrock(req, res, raw, modelId, fixtures, journal, defaults
|
|
|
183
183
|
return;
|
|
184
184
|
}
|
|
185
185
|
const completionReq = bedrockToCompletionRequest(bedrockReq, modelId);
|
|
186
|
-
const
|
|
187
|
-
|
|
186
|
+
const testId = getTestId(req);
|
|
187
|
+
const fixture = matchFixture(fixtures, completionReq, journal.getFixtureMatchCountsForTest(testId), defaults.requestTransform);
|
|
188
|
+
if (fixture) journal.incrementFixtureMatchCount(fixture, fixtures, testId);
|
|
188
189
|
if (applyChaos(res, fixture, defaults.chaos, req.headers, journal, {
|
|
189
190
|
method: req.method ?? "POST",
|
|
190
191
|
path: urlPath,
|
|
@@ -453,8 +454,9 @@ async function handleBedrockStream(req, res, raw, modelId, fixtures, journal, de
|
|
|
453
454
|
return;
|
|
454
455
|
}
|
|
455
456
|
const completionReq = bedrockToCompletionRequest(bedrockReq, modelId);
|
|
456
|
-
const
|
|
457
|
-
|
|
457
|
+
const testId = getTestId(req);
|
|
458
|
+
const fixture = matchFixture(fixtures, completionReq, journal.getFixtureMatchCountsForTest(testId), defaults.requestTransform);
|
|
459
|
+
if (fixture) journal.incrementFixtureMatchCount(fixture, fixtures, testId);
|
|
458
460
|
if (applyChaos(res, fixture, defaults.chaos, req.headers, journal, {
|
|
459
461
|
method: req.method ?? "POST",
|
|
460
462
|
path: urlPath,
|
package/dist/bedrock.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bedrock.js","names":[],"sources":["../src/bedrock.ts"],"sourcesContent":["/**\n * AWS Bedrock Claude endpoint support — invoke and invoke-with-response-stream.\n *\n * Handles four Bedrock endpoint families (split across two modules):\n *\n * This file (bedrock.ts):\n * - POST /model/{modelId}/invoke — non-streaming invoke\n * - POST /model/{modelId}/invoke-with-response-stream — binary EventStream streaming\n *\n * bedrock-converse.ts:\n * - POST /model/{modelId}/converse — Converse API (non-streaming)\n * - POST /model/{modelId}/converse-stream — Converse API (EventStream streaming)\n *\n * Translates incoming Bedrock Claude format into the ChatCompletionRequest\n * format used by the fixture router, and converts fixture responses back into\n * the appropriate Bedrock response format (JSON for invoke, AWS Event Stream\n * binary encoding for streaming).\n */\n\nimport type * as http from \"node:http\";\nimport type {\n ChatCompletionRequest,\n ChatMessage,\n Fixture,\n HandlerDefaults,\n ToolCall,\n ToolDefinition,\n} from \"./types.js\";\nimport {\n generateMessageId,\n generateToolUseId,\n isTextResponse,\n isToolCallResponse,\n isErrorResponse,\n flattenHeaders,\n} from \"./helpers.js\";\nimport { matchFixture } from \"./router.js\";\nimport { writeErrorResponse } from \"./sse-writer.js\";\nimport { writeEventStream } from \"./aws-event-stream.js\";\nimport { createInterruptionSignal } from \"./interruption.js\";\nimport type { Journal } from \"./journal.js\";\nimport type { Logger } from \"./logger.js\";\nimport { applyChaos } from \"./chaos.js\";\nimport { proxyAndRecord } from \"./recorder.js\";\n\n// ─── Bedrock Claude request types ────────────────────────────────────────────\n\ninterface BedrockContentBlock {\n type: \"text\" | \"tool_use\" | \"tool_result\" | \"image\" | \"document\";\n text?: string;\n id?: string;\n name?: string;\n input?: unknown;\n tool_use_id?: string;\n content?: string | BedrockContentBlock[];\n is_error?: boolean;\n}\n\ninterface BedrockMessage {\n role: \"user\" | \"assistant\";\n content: string | BedrockContentBlock[];\n}\n\ninterface BedrockToolDef {\n name: string;\n description?: string;\n input_schema?: object;\n}\n\ninterface BedrockRequest {\n anthropic_version?: string;\n messages: BedrockMessage[];\n system?: string | BedrockContentBlock[];\n tools?: BedrockToolDef[];\n tool_choice?: unknown;\n max_tokens: number;\n temperature?: number;\n [key: string]: unknown;\n}\n\n// ─── Input conversion: Bedrock → ChatCompletionRequest ──────────────────────\n\nfunction extractTextContent(content: string | BedrockContentBlock[]): string {\n if (typeof content === \"string\") return content;\n return content\n .filter((b) => b.type === \"text\")\n .map((b) => b.text ?? \"\")\n .join(\"\");\n}\n\nexport function bedrockToCompletionRequest(\n req: BedrockRequest,\n modelId: string,\n): ChatCompletionRequest {\n const messages: ChatMessage[] = [];\n\n // system field → system message\n if (req.system) {\n const systemText =\n typeof req.system === \"string\"\n ? req.system\n : req.system\n .filter((b) => b.type === \"text\")\n .map((b) => b.text ?? \"\")\n .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 tool_result blocks\n if (typeof msg.content !== \"string\" && Array.isArray(msg.content)) {\n const toolResults = msg.content.filter((b) => b.type === \"tool_result\");\n const textBlocks = msg.content.filter((b) => b.type === \"text\");\n\n if (toolResults.length > 0) {\n for (const tr of toolResults) {\n const resultContent =\n typeof tr.content === \"string\"\n ? tr.content\n : Array.isArray(tr.content)\n ? tr.content\n .filter((b) => b.type === \"text\")\n .map((b) => b.text ?? \"\")\n .join(\"\")\n : \"\";\n messages.push({\n role: \"tool\",\n content: resultContent,\n tool_call_id: tr.tool_use_id,\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 messages.push({\n role: \"user\",\n content: extractTextContent(msg.content),\n });\n } else if (msg.role === \"assistant\") {\n if (typeof msg.content === \"string\") {\n messages.push({ role: \"assistant\", content: msg.content });\n } else if (Array.isArray(msg.content)) {\n const toolUseBlocks = msg.content.filter((b) => b.type === \"tool_use\");\n const textContent = extractTextContent(msg.content);\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.id ?? generateToolUseId(),\n type: \"function\" as const,\n function: {\n name: b.name ?? \"\",\n arguments: typeof b.input === \"string\" ? b.input : JSON.stringify(b.input ?? {}),\n },\n })),\n });\n } else {\n messages.push({ role: \"assistant\", content: textContent || null });\n }\n } else {\n messages.push({ role: \"assistant\", content: null });\n }\n }\n }\n\n // Convert tools\n let tools: ToolDefinition[] | undefined;\n if (req.tools && req.tools.length > 0) {\n tools = req.tools.map((t) => ({\n type: \"function\" as const,\n function: {\n name: t.name,\n description: t.description,\n parameters: t.input_schema,\n },\n }));\n }\n\n return {\n model: modelId,\n messages,\n stream: false,\n temperature: req.temperature,\n tools,\n };\n}\n\n// ─── Response builders ──────────────────────────────────────────────────────\n\nfunction buildBedrockTextResponse(content: string, model: string, reasoning?: string): object {\n const contentBlocks: object[] = [];\n if (reasoning) {\n contentBlocks.push({ type: \"thinking\", thinking: reasoning });\n }\n contentBlocks.push({ type: \"text\", text: content });\n\n return {\n id: generateMessageId(),\n type: \"message\",\n role: \"assistant\",\n content: contentBlocks,\n model,\n stop_reason: \"end_turn\",\n stop_sequence: null,\n usage: { input_tokens: 0, output_tokens: 0 },\n };\n}\n\nfunction buildBedrockToolCallResponse(\n toolCalls: ToolCall[],\n model: string,\n logger: Logger,\n): object {\n return {\n id: generateMessageId(),\n type: \"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 type: \"tool_use\",\n id: tc.id || generateToolUseId(),\n name: tc.name,\n input: argsObj,\n };\n }),\n model,\n stop_reason: \"tool_use\",\n stop_sequence: null,\n usage: { input_tokens: 0, output_tokens: 0 },\n };\n}\n\n// ─── Request handler ────────────────────────────────────────────────────────\n\nexport async function handleBedrock(\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}/invoke`;\n\n let bedrockReq: BedrockRequest;\n try {\n bedrockReq = JSON.parse(raw) as BedrockRequest;\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 (!bedrockReq.messages || !Array.isArray(bedrockReq.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 // Convert to ChatCompletionRequest for fixture matching\n const completionReq = bedrockToCompletionRequest(bedrockReq, modelId);\n\n const fixture = matchFixture(\n fixtures,\n completionReq,\n journal.fixtureMatchCounts,\n defaults.requestTransform,\n );\n\n if (fixture) {\n journal.incrementFixtureMatchCount(fixture, fixtures);\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 },\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 // Anthropic-style error format (Bedrock uses Claude): { type: \"error\", error: { type, message } }\n const anthropicError = {\n type: \"error\",\n error: {\n type: response.error.type ?? \"api_error\",\n message: response.error.message,\n },\n };\n writeErrorResponse(res, status, JSON.stringify(anthropicError));\n return;\n }\n\n // Text response\n if (isTextResponse(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 = buildBedrockTextResponse(\n response.content,\n completionReq.model,\n response.reasoning,\n );\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 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 = buildBedrockToolCallResponse(response.toolCalls, completionReq.model, logger);\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\n// ─── Streaming event builders ───────────────────────────────────────────────\n\nexport function buildBedrockStreamTextEvents(\n content: string,\n chunkSize: number,\n reasoning?: string,\n): Array<{ eventType: string; payload: object }> {\n const events: Array<{ eventType: string; payload: object }> = [];\n\n events.push({\n eventType: \"messageStart\",\n payload: { role: \"assistant\" },\n });\n\n // Thinking block (emitted before text when reasoning is present)\n if (reasoning) {\n const blockIndex = 0;\n events.push({\n eventType: \"contentBlockStart\",\n payload: { contentBlockIndex: blockIndex, start: { type: \"thinking\" } },\n });\n\n for (let i = 0; i < reasoning.length; i += chunkSize) {\n const slice = reasoning.slice(i, i + chunkSize);\n events.push({\n eventType: \"contentBlockDelta\",\n payload: {\n contentBlockIndex: blockIndex,\n delta: { type: \"thinking_delta\", thinking: slice },\n },\n });\n }\n\n events.push({\n eventType: \"contentBlockStop\",\n payload: { contentBlockIndex: blockIndex },\n });\n }\n\n // Text block\n const textBlockIndex = reasoning ? 1 : 0;\n\n events.push({\n eventType: \"contentBlockStart\",\n payload: { contentBlockIndex: textBlockIndex, start: {} },\n });\n\n for (let i = 0; i < content.length; i += chunkSize) {\n const slice = content.slice(i, i + chunkSize);\n events.push({\n eventType: \"contentBlockDelta\",\n payload: {\n contentBlockIndex: textBlockIndex,\n delta: { type: \"text_delta\", text: slice },\n },\n });\n }\n\n events.push({\n eventType: \"contentBlockStop\",\n payload: { contentBlockIndex: textBlockIndex },\n });\n\n events.push({\n eventType: \"messageStop\",\n payload: { stopReason: \"end_turn\" },\n });\n\n return events;\n}\n\nexport function buildBedrockStreamToolCallEvents(\n toolCalls: ToolCall[],\n chunkSize: number,\n logger: Logger,\n): Array<{ eventType: string; payload: object }> {\n const events: Array<{ eventType: string; payload: object }> = [];\n\n events.push({\n eventType: \"messageStart\",\n payload: { role: \"assistant\" },\n });\n\n for (let tcIdx = 0; tcIdx < toolCalls.length; tcIdx++) {\n const tc = toolCalls[tcIdx];\n const toolUseId = tc.id || generateToolUseId();\n\n events.push({\n eventType: \"contentBlockStart\",\n payload: {\n contentBlockIndex: tcIdx,\n start: {\n toolUse: { toolUseId, name: tc.name },\n },\n },\n });\n\n let argsStr: string;\n try {\n const parsed = JSON.parse(tc.arguments || \"{}\");\n argsStr = JSON.stringify(parsed);\n } catch {\n logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n );\n argsStr = \"{}\";\n }\n\n for (let i = 0; i < argsStr.length; i += chunkSize) {\n const slice = argsStr.slice(i, i + chunkSize);\n events.push({\n eventType: \"contentBlockDelta\",\n payload: {\n contentBlockIndex: tcIdx,\n delta: { type: \"input_json_delta\", inputJSON: slice },\n },\n });\n }\n\n events.push({\n eventType: \"contentBlockStop\",\n payload: { contentBlockIndex: tcIdx },\n });\n }\n\n events.push({\n eventType: \"messageStop\",\n payload: { stopReason: \"tool_use\" },\n });\n\n return events;\n}\n\n// ─── Streaming request handler ──────────────────────────────────────────────\n\nexport async function handleBedrockStream(\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}/invoke-with-response-stream`;\n\n let bedrockReq: BedrockRequest;\n try {\n bedrockReq = JSON.parse(raw) as BedrockRequest;\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 (!bedrockReq.messages || !Array.isArray(bedrockReq.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 = bedrockToCompletionRequest(bedrockReq, modelId);\n\n const fixture = matchFixture(\n fixtures,\n completionReq,\n journal.fixtureMatchCounts,\n defaults.requestTransform,\n );\n\n if (fixture) {\n journal.incrementFixtureMatchCount(fixture, fixtures);\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 },\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 writeErrorResponse(res, status, JSON.stringify(response));\n return;\n }\n\n // Text response — stream as Event Stream\n if (isTextResponse(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(response.content, chunkSize, response.reasoning);\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 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(response.toolCalls, chunkSize, logger);\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.js","names":[],"sources":["../src/bedrock.ts"],"sourcesContent":["/**\n * AWS Bedrock Claude endpoint support — invoke and invoke-with-response-stream.\n *\n * Handles four Bedrock endpoint families (split across two modules):\n *\n * This file (bedrock.ts):\n * - POST /model/{modelId}/invoke — non-streaming invoke\n * - POST /model/{modelId}/invoke-with-response-stream — binary EventStream streaming\n *\n * bedrock-converse.ts:\n * - POST /model/{modelId}/converse — Converse API (non-streaming)\n * - POST /model/{modelId}/converse-stream — Converse API (EventStream streaming)\n *\n * Translates incoming Bedrock Claude format into the ChatCompletionRequest\n * format used by the fixture router, and converts fixture responses back into\n * the appropriate Bedrock response format (JSON for invoke, AWS Event Stream\n * binary encoding for streaming).\n */\n\nimport type * as http from \"node:http\";\nimport type {\n ChatCompletionRequest,\n ChatMessage,\n Fixture,\n HandlerDefaults,\n ToolCall,\n ToolDefinition,\n} from \"./types.js\";\nimport {\n generateMessageId,\n generateToolUseId,\n isTextResponse,\n isToolCallResponse,\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\";\n\n// ─── Bedrock Claude request types ────────────────────────────────────────────\n\ninterface BedrockContentBlock {\n type: \"text\" | \"tool_use\" | \"tool_result\" | \"image\" | \"document\";\n text?: string;\n id?: string;\n name?: string;\n input?: unknown;\n tool_use_id?: string;\n content?: string | BedrockContentBlock[];\n is_error?: boolean;\n}\n\ninterface BedrockMessage {\n role: \"user\" | \"assistant\";\n content: string | BedrockContentBlock[];\n}\n\ninterface BedrockToolDef {\n name: string;\n description?: string;\n input_schema?: object;\n}\n\ninterface BedrockRequest {\n anthropic_version?: string;\n messages: BedrockMessage[];\n system?: string | BedrockContentBlock[];\n tools?: BedrockToolDef[];\n tool_choice?: unknown;\n max_tokens: number;\n temperature?: number;\n [key: string]: unknown;\n}\n\n// ─── Input conversion: Bedrock → ChatCompletionRequest ──────────────────────\n\nfunction extractTextContent(content: string | BedrockContentBlock[]): string {\n if (typeof content === \"string\") return content;\n return content\n .filter((b) => b.type === \"text\")\n .map((b) => b.text ?? \"\")\n .join(\"\");\n}\n\nexport function bedrockToCompletionRequest(\n req: BedrockRequest,\n modelId: string,\n): ChatCompletionRequest {\n const messages: ChatMessage[] = [];\n\n // system field → system message\n if (req.system) {\n const systemText =\n typeof req.system === \"string\"\n ? req.system\n : req.system\n .filter((b) => b.type === \"text\")\n .map((b) => b.text ?? \"\")\n .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 tool_result blocks\n if (typeof msg.content !== \"string\" && Array.isArray(msg.content)) {\n const toolResults = msg.content.filter((b) => b.type === \"tool_result\");\n const textBlocks = msg.content.filter((b) => b.type === \"text\");\n\n if (toolResults.length > 0) {\n for (const tr of toolResults) {\n const resultContent =\n typeof tr.content === \"string\"\n ? tr.content\n : Array.isArray(tr.content)\n ? tr.content\n .filter((b) => b.type === \"text\")\n .map((b) => b.text ?? \"\")\n .join(\"\")\n : \"\";\n messages.push({\n role: \"tool\",\n content: resultContent,\n tool_call_id: tr.tool_use_id,\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 messages.push({\n role: \"user\",\n content: extractTextContent(msg.content),\n });\n } else if (msg.role === \"assistant\") {\n if (typeof msg.content === \"string\") {\n messages.push({ role: \"assistant\", content: msg.content });\n } else if (Array.isArray(msg.content)) {\n const toolUseBlocks = msg.content.filter((b) => b.type === \"tool_use\");\n const textContent = extractTextContent(msg.content);\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.id ?? generateToolUseId(),\n type: \"function\" as const,\n function: {\n name: b.name ?? \"\",\n arguments: typeof b.input === \"string\" ? b.input : JSON.stringify(b.input ?? {}),\n },\n })),\n });\n } else {\n messages.push({ role: \"assistant\", content: textContent || null });\n }\n } else {\n messages.push({ role: \"assistant\", content: null });\n }\n }\n }\n\n // Convert tools\n let tools: ToolDefinition[] | undefined;\n if (req.tools && req.tools.length > 0) {\n tools = req.tools.map((t) => ({\n type: \"function\" as const,\n function: {\n name: t.name,\n description: t.description,\n parameters: t.input_schema,\n },\n }));\n }\n\n return {\n model: modelId,\n messages,\n stream: false,\n temperature: req.temperature,\n tools,\n };\n}\n\n// ─── Response builders ──────────────────────────────────────────────────────\n\nfunction buildBedrockTextResponse(content: string, model: string, reasoning?: string): object {\n const contentBlocks: object[] = [];\n if (reasoning) {\n contentBlocks.push({ type: \"thinking\", thinking: reasoning });\n }\n contentBlocks.push({ type: \"text\", text: content });\n\n return {\n id: generateMessageId(),\n type: \"message\",\n role: \"assistant\",\n content: contentBlocks,\n model,\n stop_reason: \"end_turn\",\n stop_sequence: null,\n usage: { input_tokens: 0, output_tokens: 0 },\n };\n}\n\nfunction buildBedrockToolCallResponse(\n toolCalls: ToolCall[],\n model: string,\n logger: Logger,\n): object {\n return {\n id: generateMessageId(),\n type: \"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 type: \"tool_use\",\n id: tc.id || generateToolUseId(),\n name: tc.name,\n input: argsObj,\n };\n }),\n model,\n stop_reason: \"tool_use\",\n stop_sequence: null,\n usage: { input_tokens: 0, output_tokens: 0 },\n };\n}\n\n// ─── Request handler ────────────────────────────────────────────────────────\n\nexport async function handleBedrock(\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}/invoke`;\n\n let bedrockReq: BedrockRequest;\n try {\n bedrockReq = JSON.parse(raw) as BedrockRequest;\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 (!bedrockReq.messages || !Array.isArray(bedrockReq.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 // Convert to ChatCompletionRequest for fixture matching\n const completionReq = bedrockToCompletionRequest(bedrockReq, modelId);\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 },\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 // Anthropic-style error format (Bedrock uses Claude): { type: \"error\", error: { type, message } }\n const anthropicError = {\n type: \"error\",\n error: {\n type: response.error.type ?? \"api_error\",\n message: response.error.message,\n },\n };\n writeErrorResponse(res, status, JSON.stringify(anthropicError));\n return;\n }\n\n // Text response\n if (isTextResponse(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 = buildBedrockTextResponse(\n response.content,\n completionReq.model,\n response.reasoning,\n );\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 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 = buildBedrockToolCallResponse(response.toolCalls, completionReq.model, logger);\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\n// ─── Streaming event builders ───────────────────────────────────────────────\n\nexport function buildBedrockStreamTextEvents(\n content: string,\n chunkSize: number,\n reasoning?: string,\n): Array<{ eventType: string; payload: object }> {\n const events: Array<{ eventType: string; payload: object }> = [];\n\n events.push({\n eventType: \"messageStart\",\n payload: { role: \"assistant\" },\n });\n\n // Thinking block (emitted before text when reasoning is present)\n if (reasoning) {\n const blockIndex = 0;\n events.push({\n eventType: \"contentBlockStart\",\n payload: { contentBlockIndex: blockIndex, start: { type: \"thinking\" } },\n });\n\n for (let i = 0; i < reasoning.length; i += chunkSize) {\n const slice = reasoning.slice(i, i + chunkSize);\n events.push({\n eventType: \"contentBlockDelta\",\n payload: {\n contentBlockIndex: blockIndex,\n delta: { type: \"thinking_delta\", thinking: slice },\n },\n });\n }\n\n events.push({\n eventType: \"contentBlockStop\",\n payload: { contentBlockIndex: blockIndex },\n });\n }\n\n // Text block\n const textBlockIndex = reasoning ? 1 : 0;\n\n events.push({\n eventType: \"contentBlockStart\",\n payload: { contentBlockIndex: textBlockIndex, start: {} },\n });\n\n for (let i = 0; i < content.length; i += chunkSize) {\n const slice = content.slice(i, i + chunkSize);\n events.push({\n eventType: \"contentBlockDelta\",\n payload: {\n contentBlockIndex: textBlockIndex,\n delta: { type: \"text_delta\", text: slice },\n },\n });\n }\n\n events.push({\n eventType: \"contentBlockStop\",\n payload: { contentBlockIndex: textBlockIndex },\n });\n\n events.push({\n eventType: \"messageStop\",\n payload: { stopReason: \"end_turn\" },\n });\n\n return events;\n}\n\nexport function buildBedrockStreamToolCallEvents(\n toolCalls: ToolCall[],\n chunkSize: number,\n logger: Logger,\n): Array<{ eventType: string; payload: object }> {\n const events: Array<{ eventType: string; payload: object }> = [];\n\n events.push({\n eventType: \"messageStart\",\n payload: { role: \"assistant\" },\n });\n\n for (let tcIdx = 0; tcIdx < toolCalls.length; tcIdx++) {\n const tc = toolCalls[tcIdx];\n const toolUseId = tc.id || generateToolUseId();\n\n events.push({\n eventType: \"contentBlockStart\",\n payload: {\n contentBlockIndex: tcIdx,\n start: {\n toolUse: { toolUseId, name: tc.name },\n },\n },\n });\n\n let argsStr: string;\n try {\n const parsed = JSON.parse(tc.arguments || \"{}\");\n argsStr = JSON.stringify(parsed);\n } catch {\n logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n );\n argsStr = \"{}\";\n }\n\n for (let i = 0; i < argsStr.length; i += chunkSize) {\n const slice = argsStr.slice(i, i + chunkSize);\n events.push({\n eventType: \"contentBlockDelta\",\n payload: {\n contentBlockIndex: tcIdx,\n delta: { type: \"input_json_delta\", inputJSON: slice },\n },\n });\n }\n\n events.push({\n eventType: \"contentBlockStop\",\n payload: { contentBlockIndex: tcIdx },\n });\n }\n\n events.push({\n eventType: \"messageStop\",\n payload: { stopReason: \"tool_use\" },\n });\n\n return events;\n}\n\n// ─── Streaming request handler ──────────────────────────────────────────────\n\nexport async function handleBedrockStream(\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}/invoke-with-response-stream`;\n\n let bedrockReq: BedrockRequest;\n try {\n bedrockReq = JSON.parse(raw) as BedrockRequest;\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 (!bedrockReq.messages || !Array.isArray(bedrockReq.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 = bedrockToCompletionRequest(bedrockReq, modelId);\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 },\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 writeErrorResponse(res, status, JSON.stringify(response));\n return;\n }\n\n // Text response — stream as Event Stream\n if (isTextResponse(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(response.content, chunkSize, response.reasoning);\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 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(response.toolCalls, chunkSize, logger);\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/cli.cjs
CHANGED
|
@@ -22,7 +22,8 @@ Options:
|
|
|
22
22
|
--log-level <level> Log verbosity: silent, info, debug (default: info)
|
|
23
23
|
--validate-on-load Validate fixture schemas at startup
|
|
24
24
|
--metrics Enable Prometheus metrics at GET /metrics
|
|
25
|
-
--record Record mode: proxy unmatched requests
|
|
25
|
+
--record Record mode: proxy unmatched requests and save fixtures
|
|
26
|
+
--proxy-only Proxy mode: forward unmatched requests without saving
|
|
26
27
|
--strict Strict mode: fail on unmatched requests
|
|
27
28
|
--provider-openai <url> Upstream URL for OpenAI (used with --record)
|
|
28
29
|
--provider-anthropic <url> Upstream URL for Anthropic
|
|
@@ -85,6 +86,10 @@ const { values } = (0, node_util.parseArgs)({
|
|
|
85
86
|
type: "boolean",
|
|
86
87
|
default: false
|
|
87
88
|
},
|
|
89
|
+
"proxy-only": {
|
|
90
|
+
type: "boolean",
|
|
91
|
+
default: false
|
|
92
|
+
},
|
|
88
93
|
strict: {
|
|
89
94
|
type: "boolean",
|
|
90
95
|
default: false
|
|
@@ -175,7 +180,7 @@ let chaos;
|
|
|
175
180
|
}
|
|
176
181
|
}
|
|
177
182
|
let record;
|
|
178
|
-
if (values.record) {
|
|
183
|
+
if (values.record || values["proxy-only"]) {
|
|
179
184
|
const providers = {};
|
|
180
185
|
if (values["provider-openai"]) providers.openai = values["provider-openai"];
|
|
181
186
|
if (values["provider-anthropic"]) providers.anthropic = values["provider-anthropic"];
|
|
@@ -186,12 +191,13 @@ if (values.record) {
|
|
|
186
191
|
if (values["provider-ollama"]) providers.ollama = values["provider-ollama"];
|
|
187
192
|
if (values["provider-cohere"]) providers.cohere = values["provider-cohere"];
|
|
188
193
|
if (Object.keys(providers).length === 0) {
|
|
189
|
-
console.error(
|
|
194
|
+
console.error(`Error: --${values["proxy-only"] ? "proxy-only" : "record"} requires at least one --provider-* flag`);
|
|
190
195
|
process.exit(1);
|
|
191
196
|
}
|
|
192
197
|
record = {
|
|
193
198
|
providers,
|
|
194
|
-
fixturePath: (0, node_path.resolve)(fixturePath, "recorded")
|
|
199
|
+
fixturePath: (0, node_path.resolve)(fixturePath, "recorded"),
|
|
200
|
+
proxyOnly: values["proxy-only"]
|
|
195
201
|
};
|
|
196
202
|
}
|
|
197
203
|
async function main() {
|
package/dist/cli.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.cjs","names":["Logger","loadFixturesFromDir","loadFixtureFile","validateFixtures","createServer","watchFixtures"],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { parseArgs } from \"node:util\";\nimport { statSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { createServer } from \"./server.js\";\nimport { loadFixtureFile, loadFixturesFromDir, validateFixtures } from \"./fixture-loader.js\";\nimport { Logger, type LogLevel } from \"./logger.js\";\nimport { watchFixtures } from \"./watcher.js\";\nimport type { ChaosConfig, RecordConfig } from \"./types.js\";\n\nconst HELP = `\nUsage: llmock [options]\n\nOptions:\n -p, --port <number> Port to listen on (default: 4010)\n -h, --host <string> Host to bind to (default: 127.0.0.1)\n -f, --fixtures <path> Path to fixtures directory or file (default: ./fixtures)\n -l, --latency <ms> Latency in ms between SSE chunks (default: 0)\n -c, --chunk-size <chars> Chunk size in characters (default: 20)\n -w, --watch Watch fixture path for changes and reload\n --log-level <level> Log verbosity: silent, info, debug (default: info)\n --validate-on-load Validate fixture schemas at startup\n --metrics Enable Prometheus metrics at GET /metrics\n --record Record mode: proxy unmatched requests to real APIs\n --strict Strict mode: fail on unmatched requests\n --provider-openai <url> Upstream URL for OpenAI (used with --record)\n --provider-anthropic <url> Upstream URL for Anthropic\n --provider-gemini <url> Upstream URL for Gemini\n --provider-vertexai <url> Upstream URL for Vertex AI\n --provider-bedrock <url> Upstream URL for Bedrock\n --provider-azure <url> Upstream URL for Azure OpenAI\n --provider-ollama <url> Upstream URL for Ollama\n --provider-cohere <url> Upstream URL for Cohere\n --chaos-drop <rate> Probability (0-1) of dropping requests with 500\n --chaos-malformed <rate> Probability (0-1) of returning malformed JSON\n --chaos-disconnect <rate> Probability (0-1) of destroying connection\n --help Show this help message\n`.trim();\n\nconst { values } = parseArgs({\n options: {\n port: { type: \"string\", short: \"p\", default: \"4010\" },\n host: { type: \"string\", short: \"h\", default: \"127.0.0.1\" },\n fixtures: { type: \"string\", short: \"f\", default: \"./fixtures\" },\n latency: { type: \"string\", short: \"l\", default: \"0\" },\n \"chunk-size\": { type: \"string\", short: \"c\", default: \"20\" },\n watch: { type: \"boolean\", short: \"w\", default: false },\n \"log-level\": { type: \"string\", default: \"info\" },\n \"validate-on-load\": { type: \"boolean\", default: false },\n metrics: { type: \"boolean\", default: false },\n record: { type: \"boolean\", default: false },\n strict: { type: \"boolean\", default: false },\n \"provider-openai\": { type: \"string\" },\n \"provider-anthropic\": { type: \"string\" },\n \"provider-gemini\": { type: \"string\" },\n \"provider-vertexai\": { type: \"string\" },\n \"provider-bedrock\": { type: \"string\" },\n \"provider-azure\": { type: \"string\" },\n \"provider-ollama\": { type: \"string\" },\n \"provider-cohere\": { type: \"string\" },\n \"chaos-drop\": { type: \"string\" },\n \"chaos-malformed\": { type: \"string\" },\n \"chaos-disconnect\": { type: \"string\" },\n help: { type: \"boolean\", default: false },\n },\n strict: true,\n});\n\nif (values.help) {\n console.log(HELP);\n process.exit(0);\n}\n\nconst port = Number(values.port);\nconst host = values.host!;\nconst latency = Number(values.latency);\nconst chunkSize = Number(values[\"chunk-size\"]);\nconst fixturePath = resolve(values.fixtures!);\nconst watchMode = values.watch!;\nconst validateOnLoad = values[\"validate-on-load\"]!;\nconst logLevelStr = values[\"log-level\"]!;\n\nif (![\"silent\", \"info\", \"debug\"].includes(logLevelStr)) {\n console.error(`Invalid log-level: ${logLevelStr} (must be silent, info, or debug)`);\n process.exit(1);\n}\nconst logLevel = logLevelStr as LogLevel;\n\nif (Number.isNaN(port) || port < 0 || port > 65535) {\n console.error(`Invalid port: ${values.port}`);\n process.exit(1);\n}\n\nif (Number.isNaN(latency) || latency < 0) {\n console.error(`Invalid latency: ${values.latency}`);\n process.exit(1);\n}\n\nif (Number.isNaN(chunkSize) || chunkSize < 1) {\n console.error(`Invalid chunk-size: ${values[\"chunk-size\"]}`);\n process.exit(1);\n}\n\nconst logger = new Logger(logLevel);\n\n// Parse chaos config from CLI flags\nlet chaos: ChaosConfig | undefined;\n{\n const dropStr = values[\"chaos-drop\"];\n const malformedStr = values[\"chaos-malformed\"];\n const disconnectStr = values[\"chaos-disconnect\"];\n\n if (dropStr !== undefined || malformedStr !== undefined || disconnectStr !== undefined) {\n chaos = {};\n if (dropStr !== undefined) {\n const val = parseFloat(dropStr);\n if (isNaN(val) || val < 0 || val > 1) {\n console.error(`Invalid chaos-drop: ${dropStr} (must be 0-1)`);\n process.exit(1);\n }\n chaos.dropRate = val;\n }\n if (malformedStr !== undefined) {\n const val = parseFloat(malformedStr);\n if (isNaN(val) || val < 0 || val > 1) {\n console.error(`Invalid chaos-malformed: ${malformedStr} (must be 0-1)`);\n process.exit(1);\n }\n chaos.malformedRate = val;\n }\n if (disconnectStr !== undefined) {\n const val = parseFloat(disconnectStr);\n if (isNaN(val) || val < 0 || val > 1) {\n console.error(`Invalid chaos-disconnect: ${disconnectStr} (must be 0-1)`);\n process.exit(1);\n }\n chaos.disconnectRate = val;\n }\n }\n}\n\n// Parse record config from CLI flags\nlet record: RecordConfig | undefined;\nif (values.record) {\n const providers: RecordConfig[\"providers\"] = {};\n if (values[\"provider-openai\"]) providers.openai = values[\"provider-openai\"];\n if (values[\"provider-anthropic\"]) providers.anthropic = values[\"provider-anthropic\"];\n if (values[\"provider-gemini\"]) providers.gemini = values[\"provider-gemini\"];\n if (values[\"provider-vertexai\"]) providers.vertexai = values[\"provider-vertexai\"];\n if (values[\"provider-bedrock\"]) providers.bedrock = values[\"provider-bedrock\"];\n if (values[\"provider-azure\"]) providers.azure = values[\"provider-azure\"];\n if (values[\"provider-ollama\"]) providers.ollama = values[\"provider-ollama\"];\n if (values[\"provider-cohere\"]) providers.cohere = values[\"provider-cohere\"];\n\n if (Object.keys(providers).length === 0) {\n console.error(\"Error: --record requires at least one --provider-* flag\");\n process.exit(1);\n }\n\n record = { providers, fixturePath: resolve(fixturePath, \"recorded\") };\n}\n\nasync function main() {\n // Load fixtures from path (detect file vs directory)\n let isDir: boolean;\n let fixtures;\n try {\n const stat = statSync(fixturePath);\n isDir = stat.isDirectory();\n if (isDir) {\n fixtures = loadFixturesFromDir(fixturePath, logger);\n } else {\n fixtures = loadFixtureFile(fixturePath, logger);\n }\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n console.error(`Fixtures path not found: ${fixturePath}`);\n } else {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(`Failed to load fixtures from ${fixturePath}: ${msg}`);\n }\n process.exit(1);\n }\n\n if (fixtures.length === 0) {\n if (validateOnLoad || values.strict) {\n console.error(\"Error: No fixtures loaded and validation/strict mode is enabled — aborting.\");\n process.exit(1);\n }\n console.warn(\"Warning: No fixtures loaded. The server will return 404 for all requests.\");\n }\n\n logger.info(`Loaded ${fixtures.length} fixture(s) from ${fixturePath}`);\n\n // Validate fixtures if requested\n if (validateOnLoad) {\n const results = validateFixtures(fixtures);\n const errors = results.filter((r) => r.severity === \"error\");\n const warnings = results.filter((r) => r.severity === \"warning\");\n\n for (const w of warnings) {\n logger.warn(`Fixture ${w.fixtureIndex}: ${w.message}`);\n }\n for (const e of errors) {\n logger.error(`Fixture ${e.fixtureIndex}: ${e.message}`);\n }\n\n if (errors.length > 0) {\n console.error(`Validation failed: ${errors.length} error(s), ${warnings.length} warning(s)`);\n process.exit(1);\n }\n }\n\n const instance = await createServer(fixtures, {\n port,\n host,\n latency,\n chunkSize,\n logLevel,\n chaos,\n metrics: values.metrics,\n record,\n strict: values.strict,\n });\n\n logger.info(`aimock server listening on ${instance.url}`);\n\n // Start file watcher if requested\n let watcher: { close: () => void } | null = null;\n if (watchMode) {\n const loadFn = isDir!\n ? () => loadFixturesFromDir(fixturePath, logger)\n : () => loadFixtureFile(fixturePath, logger);\n\n watcher = watchFixtures(fixturePath, fixtures, loadFn, {\n logger,\n validate: validateOnLoad,\n validateFn: validateFixtures,\n });\n logger.info(`Watching ${fixturePath} for changes`);\n }\n\n function shutdown() {\n logger.info(\"Shutting down...\");\n if (watcher) watcher.close();\n instance.server.close(() => {\n process.exit(0);\n });\n }\n\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n}\n\nmain().catch((err) => {\n console.error(err);\n process.exit(1);\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.cjs","names":["Logger","loadFixturesFromDir","loadFixtureFile","validateFixtures","createServer","watchFixtures"],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { parseArgs } from \"node:util\";\nimport { statSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { createServer } from \"./server.js\";\nimport { loadFixtureFile, loadFixturesFromDir, validateFixtures } from \"./fixture-loader.js\";\nimport { Logger, type LogLevel } from \"./logger.js\";\nimport { watchFixtures } from \"./watcher.js\";\nimport type { ChaosConfig, RecordConfig } from \"./types.js\";\n\nconst HELP = `\nUsage: llmock [options]\n\nOptions:\n -p, --port <number> Port to listen on (default: 4010)\n -h, --host <string> Host to bind to (default: 127.0.0.1)\n -f, --fixtures <path> Path to fixtures directory or file (default: ./fixtures)\n -l, --latency <ms> Latency in ms between SSE chunks (default: 0)\n -c, --chunk-size <chars> Chunk size in characters (default: 20)\n -w, --watch Watch fixture path for changes and reload\n --log-level <level> Log verbosity: silent, info, debug (default: info)\n --validate-on-load Validate fixture schemas at startup\n --metrics Enable Prometheus metrics at GET /metrics\n --record Record mode: proxy unmatched requests and save fixtures\n --proxy-only Proxy mode: forward unmatched requests without saving\n --strict Strict mode: fail on unmatched requests\n --provider-openai <url> Upstream URL for OpenAI (used with --record)\n --provider-anthropic <url> Upstream URL for Anthropic\n --provider-gemini <url> Upstream URL for Gemini\n --provider-vertexai <url> Upstream URL for Vertex AI\n --provider-bedrock <url> Upstream URL for Bedrock\n --provider-azure <url> Upstream URL for Azure OpenAI\n --provider-ollama <url> Upstream URL for Ollama\n --provider-cohere <url> Upstream URL for Cohere\n --chaos-drop <rate> Probability (0-1) of dropping requests with 500\n --chaos-malformed <rate> Probability (0-1) of returning malformed JSON\n --chaos-disconnect <rate> Probability (0-1) of destroying connection\n --help Show this help message\n`.trim();\n\nconst { values } = parseArgs({\n options: {\n port: { type: \"string\", short: \"p\", default: \"4010\" },\n host: { type: \"string\", short: \"h\", default: \"127.0.0.1\" },\n fixtures: { type: \"string\", short: \"f\", default: \"./fixtures\" },\n latency: { type: \"string\", short: \"l\", default: \"0\" },\n \"chunk-size\": { type: \"string\", short: \"c\", default: \"20\" },\n watch: { type: \"boolean\", short: \"w\", default: false },\n \"log-level\": { type: \"string\", default: \"info\" },\n \"validate-on-load\": { type: \"boolean\", default: false },\n metrics: { type: \"boolean\", default: false },\n record: { type: \"boolean\", default: false },\n \"proxy-only\": { type: \"boolean\", default: false },\n strict: { type: \"boolean\", default: false },\n \"provider-openai\": { type: \"string\" },\n \"provider-anthropic\": { type: \"string\" },\n \"provider-gemini\": { type: \"string\" },\n \"provider-vertexai\": { type: \"string\" },\n \"provider-bedrock\": { type: \"string\" },\n \"provider-azure\": { type: \"string\" },\n \"provider-ollama\": { type: \"string\" },\n \"provider-cohere\": { type: \"string\" },\n \"chaos-drop\": { type: \"string\" },\n \"chaos-malformed\": { type: \"string\" },\n \"chaos-disconnect\": { type: \"string\" },\n help: { type: \"boolean\", default: false },\n },\n strict: true,\n});\n\nif (values.help) {\n console.log(HELP);\n process.exit(0);\n}\n\nconst port = Number(values.port);\nconst host = values.host!;\nconst latency = Number(values.latency);\nconst chunkSize = Number(values[\"chunk-size\"]);\nconst fixturePath = resolve(values.fixtures!);\nconst watchMode = values.watch!;\nconst validateOnLoad = values[\"validate-on-load\"]!;\nconst logLevelStr = values[\"log-level\"]!;\n\nif (![\"silent\", \"info\", \"debug\"].includes(logLevelStr)) {\n console.error(`Invalid log-level: ${logLevelStr} (must be silent, info, or debug)`);\n process.exit(1);\n}\nconst logLevel = logLevelStr as LogLevel;\n\nif (Number.isNaN(port) || port < 0 || port > 65535) {\n console.error(`Invalid port: ${values.port}`);\n process.exit(1);\n}\n\nif (Number.isNaN(latency) || latency < 0) {\n console.error(`Invalid latency: ${values.latency}`);\n process.exit(1);\n}\n\nif (Number.isNaN(chunkSize) || chunkSize < 1) {\n console.error(`Invalid chunk-size: ${values[\"chunk-size\"]}`);\n process.exit(1);\n}\n\nconst logger = new Logger(logLevel);\n\n// Parse chaos config from CLI flags\nlet chaos: ChaosConfig | undefined;\n{\n const dropStr = values[\"chaos-drop\"];\n const malformedStr = values[\"chaos-malformed\"];\n const disconnectStr = values[\"chaos-disconnect\"];\n\n if (dropStr !== undefined || malformedStr !== undefined || disconnectStr !== undefined) {\n chaos = {};\n if (dropStr !== undefined) {\n const val = parseFloat(dropStr);\n if (isNaN(val) || val < 0 || val > 1) {\n console.error(`Invalid chaos-drop: ${dropStr} (must be 0-1)`);\n process.exit(1);\n }\n chaos.dropRate = val;\n }\n if (malformedStr !== undefined) {\n const val = parseFloat(malformedStr);\n if (isNaN(val) || val < 0 || val > 1) {\n console.error(`Invalid chaos-malformed: ${malformedStr} (must be 0-1)`);\n process.exit(1);\n }\n chaos.malformedRate = val;\n }\n if (disconnectStr !== undefined) {\n const val = parseFloat(disconnectStr);\n if (isNaN(val) || val < 0 || val > 1) {\n console.error(`Invalid chaos-disconnect: ${disconnectStr} (must be 0-1)`);\n process.exit(1);\n }\n chaos.disconnectRate = val;\n }\n }\n}\n\n// Parse record/proxy config from CLI flags\nlet record: RecordConfig | undefined;\nif (values.record || values[\"proxy-only\"]) {\n const providers: RecordConfig[\"providers\"] = {};\n if (values[\"provider-openai\"]) providers.openai = values[\"provider-openai\"];\n if (values[\"provider-anthropic\"]) providers.anthropic = values[\"provider-anthropic\"];\n if (values[\"provider-gemini\"]) providers.gemini = values[\"provider-gemini\"];\n if (values[\"provider-vertexai\"]) providers.vertexai = values[\"provider-vertexai\"];\n if (values[\"provider-bedrock\"]) providers.bedrock = values[\"provider-bedrock\"];\n if (values[\"provider-azure\"]) providers.azure = values[\"provider-azure\"];\n if (values[\"provider-ollama\"]) providers.ollama = values[\"provider-ollama\"];\n if (values[\"provider-cohere\"]) providers.cohere = values[\"provider-cohere\"];\n\n if (Object.keys(providers).length === 0) {\n console.error(\n `Error: --${values[\"proxy-only\"] ? \"proxy-only\" : \"record\"} requires at least one --provider-* flag`,\n );\n process.exit(1);\n }\n\n record = {\n providers,\n fixturePath: resolve(fixturePath, \"recorded\"),\n proxyOnly: values[\"proxy-only\"],\n };\n}\n\nasync function main() {\n // Load fixtures from path (detect file vs directory)\n let isDir: boolean;\n let fixtures;\n try {\n const stat = statSync(fixturePath);\n isDir = stat.isDirectory();\n if (isDir) {\n fixtures = loadFixturesFromDir(fixturePath, logger);\n } else {\n fixtures = loadFixtureFile(fixturePath, logger);\n }\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n console.error(`Fixtures path not found: ${fixturePath}`);\n } else {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(`Failed to load fixtures from ${fixturePath}: ${msg}`);\n }\n process.exit(1);\n }\n\n if (fixtures.length === 0) {\n if (validateOnLoad || values.strict) {\n console.error(\"Error: No fixtures loaded and validation/strict mode is enabled — aborting.\");\n process.exit(1);\n }\n console.warn(\"Warning: No fixtures loaded. The server will return 404 for all requests.\");\n }\n\n logger.info(`Loaded ${fixtures.length} fixture(s) from ${fixturePath}`);\n\n // Validate fixtures if requested\n if (validateOnLoad) {\n const results = validateFixtures(fixtures);\n const errors = results.filter((r) => r.severity === \"error\");\n const warnings = results.filter((r) => r.severity === \"warning\");\n\n for (const w of warnings) {\n logger.warn(`Fixture ${w.fixtureIndex}: ${w.message}`);\n }\n for (const e of errors) {\n logger.error(`Fixture ${e.fixtureIndex}: ${e.message}`);\n }\n\n if (errors.length > 0) {\n console.error(`Validation failed: ${errors.length} error(s), ${warnings.length} warning(s)`);\n process.exit(1);\n }\n }\n\n const instance = await createServer(fixtures, {\n port,\n host,\n latency,\n chunkSize,\n logLevel,\n chaos,\n metrics: values.metrics,\n record,\n strict: values.strict,\n });\n\n logger.info(`aimock server listening on ${instance.url}`);\n\n // Start file watcher if requested\n let watcher: { close: () => void } | null = null;\n if (watchMode) {\n const loadFn = isDir!\n ? () => loadFixturesFromDir(fixturePath, logger)\n : () => loadFixtureFile(fixturePath, logger);\n\n watcher = watchFixtures(fixturePath, fixtures, loadFn, {\n logger,\n validate: validateOnLoad,\n validateFn: validateFixtures,\n });\n logger.info(`Watching ${fixturePath} for changes`);\n }\n\n function shutdown() {\n logger.info(\"Shutting down...\");\n if (watcher) watcher.close();\n instance.server.close(() => {\n process.exit(0);\n });\n }\n\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n}\n\nmain().catch((err) => {\n console.error(err);\n process.exit(1);\n});\n"],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -21,7 +21,8 @@ Options:
|
|
|
21
21
|
--log-level <level> Log verbosity: silent, info, debug (default: info)
|
|
22
22
|
--validate-on-load Validate fixture schemas at startup
|
|
23
23
|
--metrics Enable Prometheus metrics at GET /metrics
|
|
24
|
-
--record Record mode: proxy unmatched requests
|
|
24
|
+
--record Record mode: proxy unmatched requests and save fixtures
|
|
25
|
+
--proxy-only Proxy mode: forward unmatched requests without saving
|
|
25
26
|
--strict Strict mode: fail on unmatched requests
|
|
26
27
|
--provider-openai <url> Upstream URL for OpenAI (used with --record)
|
|
27
28
|
--provider-anthropic <url> Upstream URL for Anthropic
|
|
@@ -84,6 +85,10 @@ const { values } = parseArgs({
|
|
|
84
85
|
type: "boolean",
|
|
85
86
|
default: false
|
|
86
87
|
},
|
|
88
|
+
"proxy-only": {
|
|
89
|
+
type: "boolean",
|
|
90
|
+
default: false
|
|
91
|
+
},
|
|
87
92
|
strict: {
|
|
88
93
|
type: "boolean",
|
|
89
94
|
default: false
|
|
@@ -174,7 +179,7 @@ let chaos;
|
|
|
174
179
|
}
|
|
175
180
|
}
|
|
176
181
|
let record;
|
|
177
|
-
if (values.record) {
|
|
182
|
+
if (values.record || values["proxy-only"]) {
|
|
178
183
|
const providers = {};
|
|
179
184
|
if (values["provider-openai"]) providers.openai = values["provider-openai"];
|
|
180
185
|
if (values["provider-anthropic"]) providers.anthropic = values["provider-anthropic"];
|
|
@@ -185,12 +190,13 @@ if (values.record) {
|
|
|
185
190
|
if (values["provider-ollama"]) providers.ollama = values["provider-ollama"];
|
|
186
191
|
if (values["provider-cohere"]) providers.cohere = values["provider-cohere"];
|
|
187
192
|
if (Object.keys(providers).length === 0) {
|
|
188
|
-
console.error(
|
|
193
|
+
console.error(`Error: --${values["proxy-only"] ? "proxy-only" : "record"} requires at least one --provider-* flag`);
|
|
189
194
|
process.exit(1);
|
|
190
195
|
}
|
|
191
196
|
record = {
|
|
192
197
|
providers,
|
|
193
|
-
fixturePath: resolve(fixturePath, "recorded")
|
|
198
|
+
fixturePath: resolve(fixturePath, "recorded"),
|
|
199
|
+
proxyOnly: values["proxy-only"]
|
|
194
200
|
};
|
|
195
201
|
}
|
|
196
202
|
async function main() {
|