@copilotkit/aimock 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (368) hide show
  1. package/.claude-plugin/marketplace.json +17 -0
  2. package/.claude-plugin/plugin.json +12 -0
  3. package/LICENSE +21 -0
  4. package/README.md +82 -0
  5. package/dist/_virtual/_rolldown/runtime.cjs +29 -0
  6. package/dist/a2a-handler.cjs +203 -0
  7. package/dist/a2a-handler.cjs.map +1 -0
  8. package/dist/a2a-handler.js +199 -0
  9. package/dist/a2a-handler.js.map +1 -0
  10. package/dist/a2a-mock.cjs +292 -0
  11. package/dist/a2a-mock.cjs.map +1 -0
  12. package/dist/a2a-mock.d.cts +41 -0
  13. package/dist/a2a-mock.d.cts.map +1 -0
  14. package/dist/a2a-mock.d.ts +41 -0
  15. package/dist/a2a-mock.d.ts.map +1 -0
  16. package/dist/a2a-mock.js +290 -0
  17. package/dist/a2a-mock.js.map +1 -0
  18. package/dist/a2a-stub.cjs +4 -0
  19. package/dist/a2a-stub.d.cts +3 -0
  20. package/dist/a2a-stub.d.ts +3 -0
  21. package/dist/a2a-stub.js +3 -0
  22. package/dist/a2a-types.d.cts +68 -0
  23. package/dist/a2a-types.d.cts.map +1 -0
  24. package/dist/a2a-types.d.ts +68 -0
  25. package/dist/a2a-types.d.ts.map +1 -0
  26. package/dist/aimock-cli.cjs +112 -0
  27. package/dist/aimock-cli.cjs.map +1 -0
  28. package/dist/aimock-cli.d.cts +19 -0
  29. package/dist/aimock-cli.d.cts.map +1 -0
  30. package/dist/aimock-cli.d.ts +19 -0
  31. package/dist/aimock-cli.d.ts.map +1 -0
  32. package/dist/aimock-cli.js +110 -0
  33. package/dist/aimock-cli.js.map +1 -0
  34. package/dist/aws-event-stream.cjs +117 -0
  35. package/dist/aws-event-stream.cjs.map +1 -0
  36. package/dist/aws-event-stream.d.cts +38 -0
  37. package/dist/aws-event-stream.d.cts.map +1 -0
  38. package/dist/aws-event-stream.d.ts +38 -0
  39. package/dist/aws-event-stream.d.ts.map +1 -0
  40. package/dist/aws-event-stream.js +114 -0
  41. package/dist/aws-event-stream.js.map +1 -0
  42. package/dist/bedrock-converse.cjs +445 -0
  43. package/dist/bedrock-converse.cjs.map +1 -0
  44. package/dist/bedrock-converse.d.cts +50 -0
  45. package/dist/bedrock-converse.d.cts.map +1 -0
  46. package/dist/bedrock-converse.d.ts +50 -0
  47. package/dist/bedrock-converse.d.ts.map +1 -0
  48. package/dist/bedrock-converse.js +443 -0
  49. package/dist/bedrock-converse.js.map +1 -0
  50. package/dist/bedrock.cjs +557 -0
  51. package/dist/bedrock.cjs.map +1 -0
  52. package/dist/bedrock.d.cts +41 -0
  53. package/dist/bedrock.d.cts.map +1 -0
  54. package/dist/bedrock.d.ts +41 -0
  55. package/dist/bedrock.d.ts.map +1 -0
  56. package/dist/bedrock.js +553 -0
  57. package/dist/bedrock.js.map +1 -0
  58. package/dist/chaos.cjs +114 -0
  59. package/dist/chaos.cjs.map +1 -0
  60. package/dist/chaos.d.cts +27 -0
  61. package/dist/chaos.d.cts.map +1 -0
  62. package/dist/chaos.d.ts +27 -0
  63. package/dist/chaos.d.ts.map +1 -0
  64. package/dist/chaos.js +113 -0
  65. package/dist/chaos.js.map +1 -0
  66. package/dist/cli.cjs +268 -0
  67. package/dist/cli.cjs.map +1 -0
  68. package/dist/cli.d.cts +1 -0
  69. package/dist/cli.d.ts +1 -0
  70. package/dist/cli.js +268 -0
  71. package/dist/cli.js.map +1 -0
  72. package/dist/cohere.cjs +434 -0
  73. package/dist/cohere.cjs.map +1 -0
  74. package/dist/cohere.d.cts +34 -0
  75. package/dist/cohere.d.cts.map +1 -0
  76. package/dist/cohere.d.ts +34 -0
  77. package/dist/cohere.d.ts.map +1 -0
  78. package/dist/cohere.js +433 -0
  79. package/dist/cohere.js.map +1 -0
  80. package/dist/config-loader.cjs +111 -0
  81. package/dist/config-loader.cjs.map +1 -0
  82. package/dist/config-loader.d.cts +100 -0
  83. package/dist/config-loader.d.cts.map +1 -0
  84. package/dist/config-loader.d.ts +100 -0
  85. package/dist/config-loader.d.ts.map +1 -0
  86. package/dist/config-loader.js +107 -0
  87. package/dist/config-loader.js.map +1 -0
  88. package/dist/embeddings.cjs +150 -0
  89. package/dist/embeddings.cjs.map +1 -0
  90. package/dist/embeddings.d.cts +12 -0
  91. package/dist/embeddings.d.cts.map +1 -0
  92. package/dist/embeddings.d.ts +12 -0
  93. package/dist/embeddings.d.ts.map +1 -0
  94. package/dist/embeddings.js +150 -0
  95. package/dist/embeddings.js.map +1 -0
  96. package/dist/fixture-loader.cjs +269 -0
  97. package/dist/fixture-loader.cjs.map +1 -0
  98. package/dist/fixture-loader.d.cts +17 -0
  99. package/dist/fixture-loader.d.cts.map +1 -0
  100. package/dist/fixture-loader.d.ts +17 -0
  101. package/dist/fixture-loader.d.ts.map +1 -0
  102. package/dist/fixture-loader.js +265 -0
  103. package/dist/fixture-loader.js.map +1 -0
  104. package/dist/gemini.cjs +403 -0
  105. package/dist/gemini.cjs.map +1 -0
  106. package/dist/gemini.d.cts +10 -0
  107. package/dist/gemini.d.cts.map +1 -0
  108. package/dist/gemini.d.ts +10 -0
  109. package/dist/gemini.d.ts.map +1 -0
  110. package/dist/gemini.js +403 -0
  111. package/dist/gemini.js.map +1 -0
  112. package/dist/helpers.cjs +276 -0
  113. package/dist/helpers.cjs.map +1 -0
  114. package/dist/helpers.d.cts +39 -0
  115. package/dist/helpers.d.cts.map +1 -0
  116. package/dist/helpers.d.ts +39 -0
  117. package/dist/helpers.d.ts.map +1 -0
  118. package/dist/helpers.js +259 -0
  119. package/dist/helpers.js.map +1 -0
  120. package/dist/index.cjs +113 -0
  121. package/dist/index.d.cts +42 -0
  122. package/dist/index.d.ts +42 -0
  123. package/dist/index.js +39 -0
  124. package/dist/interruption.cjs +40 -0
  125. package/dist/interruption.cjs.map +1 -0
  126. package/dist/interruption.d.cts +15 -0
  127. package/dist/interruption.d.cts.map +1 -0
  128. package/dist/interruption.d.ts +15 -0
  129. package/dist/interruption.d.ts.map +1 -0
  130. package/dist/interruption.js +39 -0
  131. package/dist/interruption.js.map +1 -0
  132. package/dist/journal.cjs +65 -0
  133. package/dist/journal.cjs.map +1 -0
  134. package/dist/journal.d.cts +23 -0
  135. package/dist/journal.d.cts.map +1 -0
  136. package/dist/journal.d.ts +23 -0
  137. package/dist/journal.d.ts.map +1 -0
  138. package/dist/journal.js +65 -0
  139. package/dist/journal.js.map +1 -0
  140. package/dist/jsonrpc.cjs +91 -0
  141. package/dist/jsonrpc.cjs.map +1 -0
  142. package/dist/jsonrpc.d.cts +24 -0
  143. package/dist/jsonrpc.d.cts.map +1 -0
  144. package/dist/jsonrpc.d.ts +24 -0
  145. package/dist/jsonrpc.d.ts.map +1 -0
  146. package/dist/jsonrpc.js +90 -0
  147. package/dist/jsonrpc.js.map +1 -0
  148. package/dist/llmock.cjs +223 -0
  149. package/dist/llmock.cjs.map +1 -0
  150. package/dist/llmock.d.cts +70 -0
  151. package/dist/llmock.d.cts.map +1 -0
  152. package/dist/llmock.d.ts +70 -0
  153. package/dist/llmock.d.ts.map +1 -0
  154. package/dist/llmock.js +223 -0
  155. package/dist/llmock.js.map +1 -0
  156. package/dist/logger.cjs +29 -0
  157. package/dist/logger.cjs.map +1 -0
  158. package/dist/logger.d.cts +14 -0
  159. package/dist/logger.d.cts.map +1 -0
  160. package/dist/logger.d.ts +14 -0
  161. package/dist/logger.d.ts.map +1 -0
  162. package/dist/logger.js +28 -0
  163. package/dist/logger.js.map +1 -0
  164. package/dist/mcp-handler.cjs +189 -0
  165. package/dist/mcp-handler.cjs.map +1 -0
  166. package/dist/mcp-handler.js +188 -0
  167. package/dist/mcp-handler.js.map +1 -0
  168. package/dist/mcp-mock.cjs +169 -0
  169. package/dist/mcp-mock.cjs.map +1 -0
  170. package/dist/mcp-mock.d.cts +40 -0
  171. package/dist/mcp-mock.d.cts.map +1 -0
  172. package/dist/mcp-mock.d.ts +40 -0
  173. package/dist/mcp-mock.d.ts.map +1 -0
  174. package/dist/mcp-mock.js +167 -0
  175. package/dist/mcp-mock.js.map +1 -0
  176. package/dist/mcp-stub.cjs +4 -0
  177. package/dist/mcp-stub.d.cts +3 -0
  178. package/dist/mcp-stub.d.ts +3 -0
  179. package/dist/mcp-stub.js +3 -0
  180. package/dist/mcp-types.d.cts +65 -0
  181. package/dist/mcp-types.d.cts.map +1 -0
  182. package/dist/mcp-types.d.ts +65 -0
  183. package/dist/mcp-types.d.ts.map +1 -0
  184. package/dist/messages.cjs +489 -0
  185. package/dist/messages.cjs.map +1 -0
  186. package/dist/messages.d.cts +10 -0
  187. package/dist/messages.d.cts.map +1 -0
  188. package/dist/messages.d.ts +10 -0
  189. package/dist/messages.d.ts.map +1 -0
  190. package/dist/messages.js +489 -0
  191. package/dist/messages.js.map +1 -0
  192. package/dist/metrics.cjs +160 -0
  193. package/dist/metrics.cjs.map +1 -0
  194. package/dist/metrics.d.cts +24 -0
  195. package/dist/metrics.d.cts.map +1 -0
  196. package/dist/metrics.d.ts +24 -0
  197. package/dist/metrics.d.ts.map +1 -0
  198. package/dist/metrics.js +158 -0
  199. package/dist/metrics.js.map +1 -0
  200. package/dist/moderation.cjs +91 -0
  201. package/dist/moderation.cjs.map +1 -0
  202. package/dist/moderation.d.cts +23 -0
  203. package/dist/moderation.d.cts.map +1 -0
  204. package/dist/moderation.d.ts +23 -0
  205. package/dist/moderation.d.ts.map +1 -0
  206. package/dist/moderation.js +91 -0
  207. package/dist/moderation.js.map +1 -0
  208. package/dist/ndjson-writer.cjs +31 -0
  209. package/dist/ndjson-writer.cjs.map +1 -0
  210. package/dist/ndjson-writer.d.cts +17 -0
  211. package/dist/ndjson-writer.d.cts.map +1 -0
  212. package/dist/ndjson-writer.d.ts +17 -0
  213. package/dist/ndjson-writer.d.ts.map +1 -0
  214. package/dist/ndjson-writer.js +31 -0
  215. package/dist/ndjson-writer.js.map +1 -0
  216. package/dist/ollama.cjs +519 -0
  217. package/dist/ollama.cjs.map +1 -0
  218. package/dist/ollama.d.cts +34 -0
  219. package/dist/ollama.d.cts.map +1 -0
  220. package/dist/ollama.d.ts +34 -0
  221. package/dist/ollama.d.ts.map +1 -0
  222. package/dist/ollama.js +517 -0
  223. package/dist/ollama.js.map +1 -0
  224. package/dist/recorder.cjs +311 -0
  225. package/dist/recorder.cjs.map +1 -0
  226. package/dist/recorder.d.cts +23 -0
  227. package/dist/recorder.d.cts.map +1 -0
  228. package/dist/recorder.d.ts +23 -0
  229. package/dist/recorder.d.ts.map +1 -0
  230. package/dist/recorder.js +305 -0
  231. package/dist/recorder.js.map +1 -0
  232. package/dist/rerank.cjs +71 -0
  233. package/dist/rerank.cjs.map +1 -0
  234. package/dist/rerank.d.cts +22 -0
  235. package/dist/rerank.d.cts.map +1 -0
  236. package/dist/rerank.d.ts +22 -0
  237. package/dist/rerank.d.ts.map +1 -0
  238. package/dist/rerank.js +71 -0
  239. package/dist/rerank.js.map +1 -0
  240. package/dist/responses.cjs +637 -0
  241. package/dist/responses.cjs.map +1 -0
  242. package/dist/responses.d.cts +16 -0
  243. package/dist/responses.d.cts.map +1 -0
  244. package/dist/responses.d.ts +16 -0
  245. package/dist/responses.d.ts.map +1 -0
  246. package/dist/responses.js +634 -0
  247. package/dist/responses.js.map +1 -0
  248. package/dist/router.cjs +68 -0
  249. package/dist/router.cjs.map +1 -0
  250. package/dist/router.d.cts +16 -0
  251. package/dist/router.d.cts.map +1 -0
  252. package/dist/router.d.ts +16 -0
  253. package/dist/router.d.ts.map +1 -0
  254. package/dist/router.js +65 -0
  255. package/dist/router.js.map +1 -0
  256. package/dist/search.cjs +59 -0
  257. package/dist/search.cjs.map +1 -0
  258. package/dist/search.d.cts +23 -0
  259. package/dist/search.d.cts.map +1 -0
  260. package/dist/search.d.ts +23 -0
  261. package/dist/search.d.ts.map +1 -0
  262. package/dist/search.js +59 -0
  263. package/dist/search.js.map +1 -0
  264. package/dist/server.cjs +935 -0
  265. package/dist/server.cjs.map +1 -0
  266. package/dist/server.d.cts +28 -0
  267. package/dist/server.d.cts.map +1 -0
  268. package/dist/server.d.ts +28 -0
  269. package/dist/server.d.ts.map +1 -0
  270. package/dist/server.js +933 -0
  271. package/dist/server.js.map +1 -0
  272. package/dist/sse-writer.cjs +59 -0
  273. package/dist/sse-writer.cjs.map +1 -0
  274. package/dist/sse-writer.d.cts +19 -0
  275. package/dist/sse-writer.d.cts.map +1 -0
  276. package/dist/sse-writer.d.ts +19 -0
  277. package/dist/sse-writer.d.ts.map +1 -0
  278. package/dist/sse-writer.js +55 -0
  279. package/dist/sse-writer.js.map +1 -0
  280. package/dist/stream-collapse.cjs +496 -0
  281. package/dist/stream-collapse.cjs.map +1 -0
  282. package/dist/stream-collapse.d.cts +70 -0
  283. package/dist/stream-collapse.d.cts.map +1 -0
  284. package/dist/stream-collapse.d.ts +70 -0
  285. package/dist/stream-collapse.d.ts.map +1 -0
  286. package/dist/stream-collapse.js +489 -0
  287. package/dist/stream-collapse.js.map +1 -0
  288. package/dist/suite.cjs +46 -0
  289. package/dist/suite.cjs.map +1 -0
  290. package/dist/suite.d.cts +31 -0
  291. package/dist/suite.d.cts.map +1 -0
  292. package/dist/suite.d.ts +31 -0
  293. package/dist/suite.d.ts.map +1 -0
  294. package/dist/suite.js +46 -0
  295. package/dist/suite.js.map +1 -0
  296. package/dist/types.d.cts +243 -0
  297. package/dist/types.d.cts.map +1 -0
  298. package/dist/types.d.ts +243 -0
  299. package/dist/types.d.ts.map +1 -0
  300. package/dist/url.cjs +21 -0
  301. package/dist/url.cjs.map +1 -0
  302. package/dist/url.d.cts +16 -0
  303. package/dist/url.d.cts.map +1 -0
  304. package/dist/url.d.ts +16 -0
  305. package/dist/url.d.ts.map +1 -0
  306. package/dist/url.js +20 -0
  307. package/dist/url.js.map +1 -0
  308. package/dist/vector-handler.cjs +239 -0
  309. package/dist/vector-handler.cjs.map +1 -0
  310. package/dist/vector-handler.js +238 -0
  311. package/dist/vector-handler.js.map +1 -0
  312. package/dist/vector-mock.cjs +229 -0
  313. package/dist/vector-mock.cjs.map +1 -0
  314. package/dist/vector-mock.d.cts +39 -0
  315. package/dist/vector-mock.d.cts.map +1 -0
  316. package/dist/vector-mock.d.ts +39 -0
  317. package/dist/vector-mock.d.ts.map +1 -0
  318. package/dist/vector-mock.js +227 -0
  319. package/dist/vector-mock.js.map +1 -0
  320. package/dist/vector-stub.cjs +4 -0
  321. package/dist/vector-stub.d.cts +3 -0
  322. package/dist/vector-stub.d.ts +3 -0
  323. package/dist/vector-stub.js +3 -0
  324. package/dist/vector-types.d.cts +32 -0
  325. package/dist/vector-types.d.cts.map +1 -0
  326. package/dist/vector-types.d.ts +32 -0
  327. package/dist/vector-types.d.ts.map +1 -0
  328. package/dist/watcher.cjs +59 -0
  329. package/dist/watcher.cjs.map +1 -0
  330. package/dist/watcher.js +58 -0
  331. package/dist/watcher.js.map +1 -0
  332. package/dist/ws-framing.cjs +187 -0
  333. package/dist/ws-framing.cjs.map +1 -0
  334. package/dist/ws-framing.d.cts +26 -0
  335. package/dist/ws-framing.d.cts.map +1 -0
  336. package/dist/ws-framing.d.ts +26 -0
  337. package/dist/ws-framing.d.ts.map +1 -0
  338. package/dist/ws-framing.js +184 -0
  339. package/dist/ws-framing.js.map +1 -0
  340. package/dist/ws-gemini-live.cjs +364 -0
  341. package/dist/ws-gemini-live.cjs.map +1 -0
  342. package/dist/ws-gemini-live.d.cts +18 -0
  343. package/dist/ws-gemini-live.d.cts.map +1 -0
  344. package/dist/ws-gemini-live.d.ts +18 -0
  345. package/dist/ws-gemini-live.d.ts.map +1 -0
  346. package/dist/ws-gemini-live.js +364 -0
  347. package/dist/ws-gemini-live.js.map +1 -0
  348. package/dist/ws-realtime.cjs +435 -0
  349. package/dist/ws-realtime.cjs.map +1 -0
  350. package/dist/ws-realtime.d.cts +17 -0
  351. package/dist/ws-realtime.d.cts.map +1 -0
  352. package/dist/ws-realtime.d.ts +17 -0
  353. package/dist/ws-realtime.d.ts.map +1 -0
  354. package/dist/ws-realtime.js +435 -0
  355. package/dist/ws-realtime.js.map +1 -0
  356. package/dist/ws-responses.cjs +164 -0
  357. package/dist/ws-responses.cjs.map +1 -0
  358. package/dist/ws-responses.d.cts +18 -0
  359. package/dist/ws-responses.d.cts.map +1 -0
  360. package/dist/ws-responses.d.ts +18 -0
  361. package/dist/ws-responses.d.ts.map +1 -0
  362. package/dist/ws-responses.js +164 -0
  363. package/dist/ws-responses.js.map +1 -0
  364. package/fixtures/example-greeting.json +12 -0
  365. package/fixtures/example-multi-turn.json +14 -0
  366. package/fixtures/example-tool-call.json +15 -0
  367. package/package.json +118 -0
  368. package/skills/write-fixtures/SKILL.md +625 -0
@@ -0,0 +1,443 @@
1
+ import { flattenHeaders, generateToolUseId, isErrorResponse, isTextResponse, isToolCallResponse } from "./helpers.js";
2
+ import { matchFixture } from "./router.js";
3
+ import { writeErrorResponse } from "./sse-writer.js";
4
+ import { createInterruptionSignal } from "./interruption.js";
5
+ import { applyChaos } from "./chaos.js";
6
+ import { proxyAndRecord } from "./recorder.js";
7
+ import { writeEventStream } from "./aws-event-stream.js";
8
+ import { buildBedrockStreamTextEvents, buildBedrockStreamToolCallEvents } from "./bedrock.js";
9
+
10
+ //#region src/bedrock-converse.ts
11
+ function converseToCompletionRequest(req, modelId) {
12
+ const messages = [];
13
+ if (req.system && req.system.length > 0) {
14
+ const systemText = req.system.map((s) => s.text).join("");
15
+ if (systemText) messages.push({
16
+ role: "system",
17
+ content: systemText
18
+ });
19
+ }
20
+ for (const msg of req.messages) if (msg.role === "user") {
21
+ const toolResults = msg.content.filter((b) => b.toolResult);
22
+ const textBlocks = msg.content.filter((b) => b.text !== void 0 && !b.toolResult);
23
+ if (toolResults.length > 0) {
24
+ for (const block of toolResults) {
25
+ const tr = block.toolResult;
26
+ const resultContent = tr.content.map((c) => c.text ?? "").join("");
27
+ messages.push({
28
+ role: "tool",
29
+ content: resultContent,
30
+ tool_call_id: tr.toolUseId
31
+ });
32
+ }
33
+ if (textBlocks.length > 0) messages.push({
34
+ role: "user",
35
+ content: textBlocks.map((b) => b.text ?? "").join("")
36
+ });
37
+ continue;
38
+ }
39
+ const text = msg.content.filter((b) => b.text !== void 0).map((b) => b.text ?? "").join("");
40
+ messages.push({
41
+ role: "user",
42
+ content: text
43
+ });
44
+ } else if (msg.role === "assistant") {
45
+ const toolUseBlocks = msg.content.filter((b) => b.toolUse);
46
+ const textContent = msg.content.filter((b) => b.text !== void 0).map((b) => b.text ?? "").join("");
47
+ if (toolUseBlocks.length > 0) messages.push({
48
+ role: "assistant",
49
+ content: textContent || null,
50
+ tool_calls: toolUseBlocks.map((b) => ({
51
+ id: b.toolUse.toolUseId,
52
+ type: "function",
53
+ function: {
54
+ name: b.toolUse.name,
55
+ arguments: JSON.stringify(b.toolUse.input)
56
+ }
57
+ }))
58
+ });
59
+ else messages.push({
60
+ role: "assistant",
61
+ content: textContent || null
62
+ });
63
+ }
64
+ let tools;
65
+ if (req.toolConfig?.tools && req.toolConfig.tools.length > 0) tools = req.toolConfig.tools.map((t) => ({
66
+ type: "function",
67
+ function: {
68
+ name: t.toolSpec.name,
69
+ description: t.toolSpec.description,
70
+ parameters: t.toolSpec.inputSchema
71
+ }
72
+ }));
73
+ return {
74
+ model: modelId,
75
+ messages,
76
+ stream: false,
77
+ temperature: req.inferenceConfig?.temperature,
78
+ tools
79
+ };
80
+ }
81
+ function buildConverseTextResponse(content) {
82
+ return {
83
+ output: { message: {
84
+ role: "assistant",
85
+ content: [{ text: content }]
86
+ } },
87
+ stopReason: "end_turn",
88
+ usage: {
89
+ inputTokens: 0,
90
+ outputTokens: 0,
91
+ totalTokens: 0
92
+ }
93
+ };
94
+ }
95
+ function buildConverseToolCallResponse(toolCalls, logger) {
96
+ return {
97
+ output: { message: {
98
+ role: "assistant",
99
+ content: toolCalls.map((tc) => {
100
+ let argsObj;
101
+ try {
102
+ argsObj = JSON.parse(tc.arguments || "{}");
103
+ } catch {
104
+ logger.warn(`Malformed JSON in fixture tool call arguments for "${tc.name}": ${tc.arguments}`);
105
+ argsObj = {};
106
+ }
107
+ return { toolUse: {
108
+ toolUseId: tc.id || generateToolUseId(),
109
+ name: tc.name,
110
+ input: argsObj
111
+ } };
112
+ })
113
+ } },
114
+ stopReason: "tool_use",
115
+ usage: {
116
+ inputTokens: 0,
117
+ outputTokens: 0,
118
+ totalTokens: 0
119
+ }
120
+ };
121
+ }
122
+ async function handleConverse(req, res, raw, modelId, fixtures, journal, defaults, setCorsHeaders) {
123
+ const { logger } = defaults;
124
+ setCorsHeaders(res);
125
+ const urlPath = req.url ?? `/model/${modelId}/converse`;
126
+ let converseReq;
127
+ try {
128
+ converseReq = JSON.parse(raw);
129
+ } catch {
130
+ journal.add({
131
+ method: req.method ?? "POST",
132
+ path: urlPath,
133
+ headers: flattenHeaders(req.headers),
134
+ body: null,
135
+ response: {
136
+ status: 400,
137
+ fixture: null
138
+ }
139
+ });
140
+ writeErrorResponse(res, 400, JSON.stringify({ error: {
141
+ message: "Malformed JSON",
142
+ type: "invalid_request_error"
143
+ } }));
144
+ return;
145
+ }
146
+ if (!converseReq.messages || !Array.isArray(converseReq.messages)) {
147
+ journal.add({
148
+ method: req.method ?? "POST",
149
+ path: urlPath,
150
+ headers: flattenHeaders(req.headers),
151
+ body: null,
152
+ response: {
153
+ status: 400,
154
+ fixture: null
155
+ }
156
+ });
157
+ writeErrorResponse(res, 400, JSON.stringify({ error: {
158
+ message: "Invalid request: messages array is required",
159
+ type: "invalid_request_error"
160
+ } }));
161
+ return;
162
+ }
163
+ const completionReq = converseToCompletionRequest(converseReq, modelId);
164
+ const fixture = matchFixture(fixtures, completionReq, journal.fixtureMatchCounts);
165
+ if (fixture) journal.incrementFixtureMatchCount(fixture, fixtures);
166
+ if (applyChaos(res, fixture, defaults.chaos, req.headers, journal, {
167
+ method: req.method ?? "POST",
168
+ path: urlPath,
169
+ headers: flattenHeaders(req.headers),
170
+ body: completionReq
171
+ }, defaults.registry, defaults.logger)) return;
172
+ if (!fixture) {
173
+ if (defaults.record) {
174
+ if (await proxyAndRecord(req, res, completionReq, "bedrock", urlPath, fixtures, defaults, raw)) {
175
+ journal.add({
176
+ method: req.method ?? "POST",
177
+ path: urlPath,
178
+ headers: flattenHeaders(req.headers),
179
+ body: completionReq,
180
+ response: {
181
+ status: res.statusCode ?? 200,
182
+ fixture: null
183
+ }
184
+ });
185
+ return;
186
+ }
187
+ }
188
+ const strictStatus = defaults.strict ? 503 : 404;
189
+ const strictMessage = defaults.strict ? "Strict mode: no fixture matched" : "No fixture matched";
190
+ if (defaults.strict) logger.error(`STRICT: No fixture matched for ${req.method ?? "POST"} ${urlPath}`);
191
+ journal.add({
192
+ method: req.method ?? "POST",
193
+ path: urlPath,
194
+ headers: flattenHeaders(req.headers),
195
+ body: completionReq,
196
+ response: {
197
+ status: strictStatus,
198
+ fixture: null
199
+ }
200
+ });
201
+ writeErrorResponse(res, strictStatus, JSON.stringify({ error: {
202
+ message: strictMessage,
203
+ type: "invalid_request_error"
204
+ } }));
205
+ return;
206
+ }
207
+ const response = fixture.response;
208
+ if (isErrorResponse(response)) {
209
+ const status = response.status ?? 500;
210
+ journal.add({
211
+ method: req.method ?? "POST",
212
+ path: urlPath,
213
+ headers: flattenHeaders(req.headers),
214
+ body: completionReq,
215
+ response: {
216
+ status,
217
+ fixture
218
+ }
219
+ });
220
+ writeErrorResponse(res, status, JSON.stringify(response));
221
+ return;
222
+ }
223
+ if (isTextResponse(response)) {
224
+ journal.add({
225
+ method: req.method ?? "POST",
226
+ path: urlPath,
227
+ headers: flattenHeaders(req.headers),
228
+ body: completionReq,
229
+ response: {
230
+ status: 200,
231
+ fixture
232
+ }
233
+ });
234
+ const body = buildConverseTextResponse(response.content);
235
+ res.writeHead(200, { "Content-Type": "application/json" });
236
+ res.end(JSON.stringify(body));
237
+ return;
238
+ }
239
+ if (isToolCallResponse(response)) {
240
+ journal.add({
241
+ method: req.method ?? "POST",
242
+ path: urlPath,
243
+ headers: flattenHeaders(req.headers),
244
+ body: completionReq,
245
+ response: {
246
+ status: 200,
247
+ fixture
248
+ }
249
+ });
250
+ const body = buildConverseToolCallResponse(response.toolCalls, logger);
251
+ res.writeHead(200, { "Content-Type": "application/json" });
252
+ res.end(JSON.stringify(body));
253
+ return;
254
+ }
255
+ journal.add({
256
+ method: req.method ?? "POST",
257
+ path: urlPath,
258
+ headers: flattenHeaders(req.headers),
259
+ body: completionReq,
260
+ response: {
261
+ status: 500,
262
+ fixture
263
+ }
264
+ });
265
+ writeErrorResponse(res, 500, JSON.stringify({ error: {
266
+ message: "Fixture response did not match any known type",
267
+ type: "server_error"
268
+ } }));
269
+ }
270
+ async function handleConverseStream(req, res, raw, modelId, fixtures, journal, defaults, setCorsHeaders) {
271
+ const { logger } = defaults;
272
+ setCorsHeaders(res);
273
+ const urlPath = req.url ?? `/model/${modelId}/converse-stream`;
274
+ let converseReq;
275
+ try {
276
+ converseReq = JSON.parse(raw);
277
+ } catch {
278
+ journal.add({
279
+ method: req.method ?? "POST",
280
+ path: urlPath,
281
+ headers: flattenHeaders(req.headers),
282
+ body: null,
283
+ response: {
284
+ status: 400,
285
+ fixture: null
286
+ }
287
+ });
288
+ writeErrorResponse(res, 400, JSON.stringify({ error: {
289
+ message: "Malformed JSON",
290
+ type: "invalid_request_error"
291
+ } }));
292
+ return;
293
+ }
294
+ if (!converseReq.messages || !Array.isArray(converseReq.messages)) {
295
+ journal.add({
296
+ method: req.method ?? "POST",
297
+ path: urlPath,
298
+ headers: flattenHeaders(req.headers),
299
+ body: null,
300
+ response: {
301
+ status: 400,
302
+ fixture: null
303
+ }
304
+ });
305
+ writeErrorResponse(res, 400, JSON.stringify({ error: {
306
+ message: "Invalid request: messages array is required",
307
+ type: "invalid_request_error"
308
+ } }));
309
+ return;
310
+ }
311
+ const completionReq = converseToCompletionRequest(converseReq, modelId);
312
+ const fixture = matchFixture(fixtures, completionReq, journal.fixtureMatchCounts);
313
+ if (fixture) journal.incrementFixtureMatchCount(fixture, fixtures);
314
+ if (applyChaos(res, fixture, defaults.chaos, req.headers, journal, {
315
+ method: req.method ?? "POST",
316
+ path: urlPath,
317
+ headers: flattenHeaders(req.headers),
318
+ body: completionReq
319
+ }, defaults.registry, defaults.logger)) return;
320
+ if (!fixture) {
321
+ if (defaults.record) {
322
+ if (await proxyAndRecord(req, res, completionReq, "bedrock", urlPath, fixtures, defaults, raw)) {
323
+ journal.add({
324
+ method: req.method ?? "POST",
325
+ path: urlPath,
326
+ headers: flattenHeaders(req.headers),
327
+ body: completionReq,
328
+ response: {
329
+ status: res.statusCode ?? 200,
330
+ fixture: null
331
+ }
332
+ });
333
+ return;
334
+ }
335
+ }
336
+ const strictStatus = defaults.strict ? 503 : 404;
337
+ const strictMessage = defaults.strict ? "Strict mode: no fixture matched" : "No fixture matched";
338
+ if (defaults.strict) logger.error(`STRICT: No fixture matched for ${req.method ?? "POST"} ${urlPath}`);
339
+ journal.add({
340
+ method: req.method ?? "POST",
341
+ path: urlPath,
342
+ headers: flattenHeaders(req.headers),
343
+ body: completionReq,
344
+ response: {
345
+ status: strictStatus,
346
+ fixture: null
347
+ }
348
+ });
349
+ writeErrorResponse(res, strictStatus, JSON.stringify({ error: {
350
+ message: strictMessage,
351
+ type: "invalid_request_error"
352
+ } }));
353
+ return;
354
+ }
355
+ const response = fixture.response;
356
+ const latency = fixture.latency ?? defaults.latency;
357
+ const chunkSize = Math.max(1, fixture.chunkSize ?? defaults.chunkSize);
358
+ if (isErrorResponse(response)) {
359
+ const status = response.status ?? 500;
360
+ journal.add({
361
+ method: req.method ?? "POST",
362
+ path: urlPath,
363
+ headers: flattenHeaders(req.headers),
364
+ body: completionReq,
365
+ response: {
366
+ status,
367
+ fixture
368
+ }
369
+ });
370
+ writeErrorResponse(res, status, JSON.stringify(response));
371
+ return;
372
+ }
373
+ if (isTextResponse(response)) {
374
+ const journalEntry = journal.add({
375
+ method: req.method ?? "POST",
376
+ path: urlPath,
377
+ headers: flattenHeaders(req.headers),
378
+ body: completionReq,
379
+ response: {
380
+ status: 200,
381
+ fixture
382
+ }
383
+ });
384
+ const events = buildBedrockStreamTextEvents(response.content, chunkSize);
385
+ const interruption = createInterruptionSignal(fixture);
386
+ if (!await writeEventStream(res, events, {
387
+ latency,
388
+ streamingProfile: fixture.streamingProfile,
389
+ signal: interruption?.signal,
390
+ onChunkSent: interruption?.tick
391
+ })) {
392
+ if (!res.writableEnded) res.destroy();
393
+ journalEntry.response.interrupted = true;
394
+ journalEntry.response.interruptReason = interruption?.reason();
395
+ }
396
+ interruption?.cleanup();
397
+ return;
398
+ }
399
+ if (isToolCallResponse(response)) {
400
+ const journalEntry = journal.add({
401
+ method: req.method ?? "POST",
402
+ path: urlPath,
403
+ headers: flattenHeaders(req.headers),
404
+ body: completionReq,
405
+ response: {
406
+ status: 200,
407
+ fixture
408
+ }
409
+ });
410
+ const events = buildBedrockStreamToolCallEvents(response.toolCalls, chunkSize, logger);
411
+ const interruption = createInterruptionSignal(fixture);
412
+ if (!await writeEventStream(res, events, {
413
+ latency,
414
+ streamingProfile: fixture.streamingProfile,
415
+ signal: interruption?.signal,
416
+ onChunkSent: interruption?.tick
417
+ })) {
418
+ if (!res.writableEnded) res.destroy();
419
+ journalEntry.response.interrupted = true;
420
+ journalEntry.response.interruptReason = interruption?.reason();
421
+ }
422
+ interruption?.cleanup();
423
+ return;
424
+ }
425
+ journal.add({
426
+ method: req.method ?? "POST",
427
+ path: urlPath,
428
+ headers: flattenHeaders(req.headers),
429
+ body: completionReq,
430
+ response: {
431
+ status: 500,
432
+ fixture
433
+ }
434
+ });
435
+ writeErrorResponse(res, 500, JSON.stringify({ error: {
436
+ message: "Fixture response did not match any known type",
437
+ type: "server_error"
438
+ } }));
439
+ }
440
+
441
+ //#endregion
442
+ export { converseToCompletionRequest, handleConverse, handleConverseStream };
443
+ //# sourceMappingURL=bedrock-converse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bedrock-converse.js","names":[],"sources":["../src/bedrock-converse.ts"],"sourcesContent":["/**\n * AWS Bedrock Converse API support.\n *\n * Translates incoming Converse and Converse-stream requests (Bedrock Converse\n * format) into the ChatCompletionRequest format used by the fixture router,\n * and converts fixture responses back into Converse API format — either a\n * single JSON response or an Event Stream binary stream.\n */\n\nimport type * as http from \"node:http\";\nimport type {\n ChatCompletionRequest,\n ChatMessage,\n Fixture,\n HandlerDefaults,\n ToolCall,\n ToolDefinition,\n} from \"./types.js\";\nimport {\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\";\nimport { buildBedrockStreamTextEvents, buildBedrockStreamToolCallEvents } from \"./bedrock.js\";\n\n// ─── Converse request types ─────────────────────────────────────────────────\n\ninterface ConverseContentBlock {\n text?: string;\n toolUse?: { toolUseId: string; name: string; input: object };\n toolResult?: { toolUseId: string; content: { text?: string }[] };\n}\n\ninterface ConverseMessage {\n role: \"user\" | \"assistant\";\n content: ConverseContentBlock[];\n}\n\ninterface ConverseToolSpec {\n name: string;\n description?: string;\n inputSchema?: object;\n}\n\ninterface ConverseRequest {\n messages: ConverseMessage[];\n system?: { text: string }[];\n inferenceConfig?: { maxTokens?: number; temperature?: number };\n toolConfig?: { tools: { toolSpec: ConverseToolSpec }[] };\n}\n\n// ─── Input conversion: Converse → ChatCompletionRequest ─────────────────────\n\nexport function converseToCompletionRequest(\n req: ConverseRequest,\n modelId: string,\n): ChatCompletionRequest {\n const messages: ChatMessage[] = [];\n\n // system field → system message\n if (req.system && req.system.length > 0) {\n const systemText = req.system.map((s) => s.text).join(\"\");\n if (systemText) {\n messages.push({ role: \"system\", content: systemText });\n }\n }\n\n for (const msg of req.messages) {\n if (msg.role === \"user\") {\n // Check for toolResult blocks\n const toolResults = msg.content.filter((b) => b.toolResult);\n const textBlocks = msg.content.filter((b) => b.text !== undefined && !b.toolResult);\n\n if (toolResults.length > 0) {\n for (const block of toolResults) {\n const tr = block.toolResult!;\n const resultContent = tr.content.map((c) => c.text ?? \"\").join(\"\");\n messages.push({\n role: \"tool\",\n content: resultContent,\n tool_call_id: tr.toolUseId,\n });\n }\n if (textBlocks.length > 0) {\n messages.push({\n role: \"user\",\n content: textBlocks.map((b) => b.text ?? \"\").join(\"\"),\n });\n }\n continue;\n }\n\n // Plain user message\n const text = msg.content\n .filter((b) => b.text !== undefined)\n .map((b) => b.text ?? \"\")\n .join(\"\");\n messages.push({ role: \"user\", content: text });\n } else if (msg.role === \"assistant\") {\n const toolUseBlocks = msg.content.filter((b) => b.toolUse);\n const textContent = msg.content\n .filter((b) => b.text !== undefined)\n .map((b) => b.text ?? \"\")\n .join(\"\");\n\n if (toolUseBlocks.length > 0) {\n messages.push({\n role: \"assistant\",\n content: textContent || null,\n tool_calls: toolUseBlocks.map((b) => ({\n id: b.toolUse!.toolUseId,\n type: \"function\" as const,\n function: {\n name: b.toolUse!.name,\n arguments: JSON.stringify(b.toolUse!.input),\n },\n })),\n });\n } else {\n messages.push({ role: \"assistant\", content: textContent || null });\n }\n }\n }\n\n // Convert tools\n let tools: ToolDefinition[] | undefined;\n if (req.toolConfig?.tools && req.toolConfig.tools.length > 0) {\n tools = req.toolConfig.tools.map((t) => ({\n type: \"function\" as const,\n function: {\n name: t.toolSpec.name,\n description: t.toolSpec.description,\n parameters: t.toolSpec.inputSchema,\n },\n }));\n }\n\n return {\n model: modelId,\n messages,\n stream: false,\n temperature: req.inferenceConfig?.temperature,\n tools,\n };\n}\n\n// ─── Response builders ──────────────────────────────────────────────────────\n\nfunction buildConverseTextResponse(content: string): object {\n return {\n output: {\n message: {\n role: \"assistant\",\n content: [{ text: content }],\n },\n },\n stopReason: \"end_turn\",\n usage: { inputTokens: 0, outputTokens: 0, totalTokens: 0 },\n };\n}\n\nfunction buildConverseToolCallResponse(toolCalls: ToolCall[], logger: Logger): object {\n return {\n output: {\n message: {\n role: \"assistant\",\n content: toolCalls.map((tc) => {\n let argsObj: unknown;\n try {\n argsObj = JSON.parse(tc.arguments || \"{}\");\n } catch {\n logger.warn(\n `Malformed JSON in fixture tool call arguments for \"${tc.name}\": ${tc.arguments}`,\n );\n argsObj = {};\n }\n return {\n toolUse: {\n toolUseId: tc.id || generateToolUseId(),\n name: tc.name,\n input: argsObj,\n },\n };\n }),\n },\n },\n stopReason: \"tool_use\",\n usage: { inputTokens: 0, outputTokens: 0, totalTokens: 0 },\n };\n}\n\n// ─── Request handlers ───────────────────────────────────────────────────────\n\nexport async function handleConverse(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n raw: string,\n modelId: string,\n fixtures: Fixture[],\n journal: Journal,\n defaults: HandlerDefaults,\n setCorsHeaders: (res: http.ServerResponse) => void,\n): Promise<void> {\n const { logger } = defaults;\n setCorsHeaders(res);\n\n const urlPath = req.url ?? `/model/${modelId}/converse`;\n\n let converseReq: ConverseRequest;\n try {\n converseReq = JSON.parse(raw) as ConverseRequest;\n } catch {\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: {\n message: \"Malformed JSON\",\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n if (!converseReq.messages || !Array.isArray(converseReq.messages)) {\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: {\n message: \"Invalid request: messages array is required\",\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n const completionReq = converseToCompletionRequest(converseReq, modelId);\n\n const fixture = matchFixture(fixtures, completionReq, journal.fixtureMatchCounts);\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 writeErrorResponse(res, status, JSON.stringify(response));\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 = buildConverseTextResponse(response.content);\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 = buildConverseToolCallResponse(response.toolCalls, 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\nexport async function handleConverseStream(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n raw: string,\n modelId: string,\n fixtures: Fixture[],\n journal: Journal,\n defaults: HandlerDefaults,\n setCorsHeaders: (res: http.ServerResponse) => void,\n): Promise<void> {\n const { logger } = defaults;\n setCorsHeaders(res);\n\n const urlPath = req.url ?? `/model/${modelId}/converse-stream`;\n\n let converseReq: ConverseRequest;\n try {\n converseReq = JSON.parse(raw) as ConverseRequest;\n } catch {\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: {\n message: \"Malformed JSON\",\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n if (!converseReq.messages || !Array.isArray(converseReq.messages)) {\n journal.add({\n method: req.method ?? \"POST\",\n path: urlPath,\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: {\n message: \"Invalid request: messages array is required\",\n type: \"invalid_request_error\",\n },\n }),\n );\n return;\n }\n\n const completionReq = converseToCompletionRequest(converseReq, modelId);\n\n const fixture = matchFixture(fixtures, completionReq, journal.fixtureMatchCounts);\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);\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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"}