@crvouga/mockingbird-service-bedrock 3.6.0 → 3.8.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/CHANGELOG.md CHANGED
@@ -1,6 +1,23 @@
1
1
  # Changelog — @crvouga/mockingbird-service-bedrock
2
2
 
3
- ## 3.6.0 (2026-10-17)
3
+ ## 3.8.0 (2026-10-21)
4
+
5
+ ### Features
6
+
7
+ - raise the serve and fleet body limit to the S3 maximum ([86b9e2b](https://github.com/crvouga/mockingbird/commit/86b9e2b80bcaaaef57f52edbac50b27da0b42f33))
8
+
9
+ ### Fixes and improvements
10
+
11
+ - finish junction, notion and bedrock docs and tests ([f1b4ccb](https://github.com/crvouga/mockingbird/commit/f1b4ccb4441144b5151b536aaacc8519b2e86075))
12
+ - reject unknown script match keys and add schema, document and cache validation ([af0c60d](https://github.com/crvouga/mockingbird/commit/af0c60d672ec6810fca1b9a69559f34181303499))
13
+
14
+ ## 3.7.0 (2026-10-18)
15
+
16
+ ### Features
17
+
18
+ - resolve the agent-reported issue queue in one batch ([25c52b6](https://github.com/crvouga/mockingbird/commit/25c52b668a53ddb80b968419601a20abf33f956b))
19
+
20
+ ## 3.6.0 (2026-10-16)
4
21
 
5
22
  ### Features
6
23
 
package/README.md CHANGED
@@ -106,7 +106,7 @@ HTTP/1.1 only — fine for the AI SDK, not for the SDK v3 Bedrock client.)
106
106
  | --- | --- |
107
107
  | `POST /model/{modelId}/converse` | Converse JSON: `output.message.content[]` (`text`, `toolUse`, `reasoningContent`), `stopReason`, `usage` (with `cacheRead/WriteInputTokens` when a `cachePoint` is present), `metrics`, `trace.guardrail` (with `guardrailConfig.trace: "enabled"`), `x-amzn-RequestId`. |
108
108
  | `POST /model/{modelId}/converse-stream` | The same answer as event frames: `messageStart`, `contentBlockStart` (tool use), `contentBlockDelta` (`text`, `toolUse.input` partial JSON, `reasoningContent`), `contentBlockStop`, `messageStop`, `metadata`; exception frames mid-stream. |
109
- | `POST /model/{modelId}/invoke` | `amazon.titan-embed-text-*`: `{embedding, inputTextTokenCount}` — a deterministic unit vector from SHA-256(`inputText`) (1024-d by default; `dimensions` 256/512/1024). Claude models: an Anthropic Messages body in, a Messages response out. |
109
+ | `POST /model/{modelId}/invoke` | `amazon.titan-embed-text-*`: `{embedding, inputTextTokenCount}` — a deterministic unit vector from SHA-256(`inputText`) (1024-d by default; `dimensions` 256/512/1024), or a lexical one with `embeddingMode: "lexical"` (see Settings). Claude models: an Anthropic Messages body in, a Messages response out. |
110
110
  | `POST /model/{modelId}/invoke-with-bidirectional-stream` | Nova Sonic (`*sonic*`), HTTP/2 duplex: reads `chunk` events as they arrive (SigV4 envelopes unwrapped), answers each user turn with `textOutput` + 24 kHz PCM tone `audioOutput` + `toolUse`, then `usageEvent`; `completionEnd` after `sessionEnd`. |
111
111
  | `POST /harnesses/invoke?harnessArn=` | AgentCore harness stream: `messageStart`, `contentBlockDelta` (`text` or `toolResult[]`), `contentBlockStop`, `messageStop`, `metadata`; `validationException` / `internalServerException` / `runtimeClientError` frames. |
112
112
 
@@ -114,7 +114,8 @@ HTTP/1.1 only — fine for the AI SDK, not for the SDK v3 Bedrock client.)
114
114
  accepted without verification. Request checks Bedrock makes and our code branches on are
115
115
  enforced: role alternation, first/last message is the user (assistant **prefill** is rejected
116
116
  for Claude 4.5+), tool-use/tool-result pairing, `toolConfig` required with tool blocks, a
117
- document needs a sibling text block, `temperature` + `top_p` together on Claude 4.5+. Errors are
117
+ document needs a sibling text block, `temperature` + `top_p` together on Claude 4.5+, plus the
118
+ best-guess checks listed under "Best guesses, not oracle-verified". Errors are
118
119
  `x-amzn-ErrorType: <Name>:http://internal.amazon.com/coral/com.amazon.bedrock/` + `{"message"}`.
119
120
  Output longer than `maxTokens` (≈4 chars/token) is cut with `stopReason: "max_tokens"`.
120
121
 
@@ -127,8 +128,16 @@ how many calls it answers.
127
128
  - **Match keys:** `modelId` (glob), `operation` (`Converse`, `ConverseStream`, `InvokeModel`,
128
129
  `InvokeModelWithBidirectionalStream`, `InvokeHarness`), `lastUserText` (string = contains, or
129
130
  `{contains, regex, flags}`), `systemHash` (SHA-256 hex of the system text blocks joined with
130
- `\n`), `toolsInclude`, `toolChoice` (`auto` / `any` / a tool name), `hasDocument`, `hasImage`,
131
- `callIndex` (0-based index of the call in the namespace).
131
+ `\n`), `systemText` (the same joined system text, `cachePoint` blocks skipped; string =
132
+ case-insensitive contains, or `{contains, regex, flags}`; a call with no system prompt never
133
+ matches; for `InvokeModel` the Claude `system` string or text blocks, never stored),
134
+ `jsonSchemaName` (`outputConfig.textFormat.structure.jsonSchema.name`; string =
135
+ case-insensitive equality, or `{contains, regex, flags}`; a call without a named `outputConfig`
136
+ schema never matches), `toolsInclude`, `toolChoice` (`auto` / `any` / a tool name), `hasDocument`, `hasImage`,
137
+ `callIndex` (0-based index of the call in the namespace). `match` is a closed set: an unknown
138
+ or misspelled key (`lastUserTxt`) or a malformed criterion makes `PUT`/`POST /__admin/scripts`
139
+ answer 400 (`scripts[0].match.lastUserTxt: unknown match field (one of ...)`) instead of
140
+ silently matching every call; the same goes for an unknown key inside a text match.
132
141
  - **Turn selection** reads the conversation, not server state: turn *n* answers the call that
133
142
  comes after *n* assistant messages since the member last said something. So turn 0 is the
134
143
  first call of a user turn, turn 1 is the call that resumes after a tool result, and every new
@@ -166,6 +175,7 @@ applies to every model and harness call in the calling namespace):
166
175
  | `latency` (`latencyMs`) | the response starts after 2 s on the emulator clock |
167
176
  | `truncated_frame` | the stream stops half-way through a frame (both decoders throw) |
168
177
  | `model_timeout`, `service_unavailable`, `access_denied`, `internal_server` | 408 / 503 / 403 / 500 with the matching `x-amzn-ErrorType` |
178
+ | `resource_not_found` | 404 `ResourceNotFoundException` ("The specified resource ARN was not found. Check the ARN and try again.", per the Converse API reference), before any frame, on Converse, ConverseStream and InvokeModel |
169
179
 
170
180
  Chunk pacing and latency wait on the **emulator clock**: freeze it (`POST /__admin/clock
171
181
  {"freeze": true}`) and advance it to release each chunk, so time-to-first-token tests are exact.
@@ -179,12 +189,53 @@ Chunk pacing and latency wait on the **emulator clock**: freeze it (`POST /__adm
179
189
  | `GET /__admin/scripts` | Scripts plus `stats` (`calls`, `scripted`, `unscripted`, `byScript`, `byFallback`, `byOperation`). |
180
190
  | `DELETE /__admin/scripts[?id=]` | Remove one or all. |
181
191
  | `GET /__admin/model-metrics` | Just the stats. |
182
- | `GET/PUT /__admin/settings` | `defaultText`, `chunkSize` (16), `delayMsPerChunk` (0), `audioTurnChunks` (0: a Nova Sonic spoken turn ends at the audio `contentEnd`; n: after n audio frames). |
192
+ | `GET/PUT /__admin/settings` | `defaultText`, `chunkSize` (16), `delayMsPerChunk` (0), `audioTurnChunks` (0: a Nova Sonic spoken turn ends at the audio `contentEnd`; n: after n audio frames), `embeddingMode` (`sha256` default, or `lexical`), `validatePromptCaching` (`true` default; `false` disables the model check on `cachePoint`). |
193
+
194
+ `embeddingMode: "lexical"` (opt-in; the test-control request in #522, not a Bedrock behaviour)
195
+ keeps Titan vectors deterministic and unit length but makes them similarity-preserving: each
196
+ word (lowercased, accents and punctuation dropped) adds to a SHA-256-chosen signed dimension, so
197
+ texts differing only in case, punctuation or spacing have cosine similarity 1, texts sharing most
198
+ words score high, and texts with no word in common score near 0. It is bag-of-words, not a
199
+ language model: synonyms ("evening" / "night") stay apart. Scripted per-text vectors are not
200
+ implemented. `normalize: false` is ignored in both modes (vectors are always unit length).
183
201
 
184
202
  The request journal (`GET /__admin/requests`) records per call only `modelId`, `script` (or
185
203
  `unscripted:<default>`), tool names, flags (`cachePoint`, `guardrail`, `document`, `image`,
186
204
  `structured:<form>`), `stopReason` and token counts — never prompt or message text.
187
205
 
206
+ ### Best guesses, not oracle-verified
207
+
208
+ These request checks come from the AWS documentation and what consumers reported about live
209
+ Bedrock, not from observing the service; the exact message text of the ones marked "ours" is an
210
+ emulator choice. All answer `400 ValidationException`.
211
+
212
+ - **Structured-output schemas** (`outputConfig.textFormat.structure.jsonSchema.schema`, Converse
213
+ and ConverseStream, [docs](https://docs.aws.amazon.com/bedrock/latest/userguide/structured-output.html)):
214
+ `schema` that is not a JSON object (ours); `oneOf` (`Schema type 'oneOf' is not supported`);
215
+ `additionalProperties` set to anything other than `false` on any node, `true` or a sub-schema
216
+ (`For 'object' type, 'additionalProperties: <X>' is not supported. Please set
217
+ 'additionalProperties' to false`); a string-only `enum` combined with a union `type` such as
218
+ `["string","null"]` (ours); `minimum`, `maximum`, `multipleOf`, `minLength`, `maxLength`,
219
+ `minItems` above 1, an external `$ref`, and a recursive `$ref` cycle (ours). An omitted
220
+ `additionalProperties` and `anyOf` / `allOf` / internal `$ref` / `$defs` pass. Only the
221
+ `outputConfig` form is checked, not `additionalModelRequestFields.output_config` nor
222
+ `InvokeModel` bodies.
223
+ - **Document names** (`document.name`, [API reference](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_DocumentBlock.html)):
224
+ 1 to 200 characters of ASCII letters, digits, whitespace, hyphens, parentheses and square
225
+ brackets, with no run of two whitespace characters. The message is the one a consumer recorded
226
+ from live Bedrock.
227
+ - **`cachePoint`** ([docs](https://docs.aws.amazon.com/bedrock/latest/userguide/prompt-caching.html)):
228
+ a `cachePoint` content block directly after a `document` block (consumer report; message ours);
229
+ and, on Converse / ConverseStream, a `cachePoint` in `system`, `messages` or `toolConfig.tools`
230
+ for a model outside the documented list (Claude 3.5 Haiku, 3.5 Sonnet v2, 3.7 Sonnet, Claude
231
+ 4 and later Opus / Sonnet / Haiku, Fable and Mythos; Nova Micro / Lite / Pro / 2 Lite), matched
232
+ on the family inside plain, `us.` / `global.` and ARN forms. The list grows: turn the model
233
+ check off with `PUT /__admin/settings {"validatePromptCaching": false}`. The `ttl` field is
234
+ not checked.
235
+ - **Unknown model ids** still answer normally (`modelId` is any id). A `knownModels` setting that
236
+ makes an unknown id fail was requested in #523 but not built: whether live Bedrock answers
237
+ `ResourceNotFoundException` or `ValidationException` for it has not been observed.
238
+
188
239
  ### Namespaces
189
240
 
190
241
  `x-mockingbird-namespace`, a `/__admin/ns/<name>` prefix on the endpoint URL, or by credential: the SDKs
@@ -213,6 +264,7 @@ cannot add headers, so map each worker's access key id:
213
264
  | `accessKeyCredential` | function | The SigV4 access key id of a request (how credentials map to namespaces). |
214
265
  | `clockSleep` | function | A sleep that waits on a (possibly frozen) emulator clock. |
215
266
  | `titanEmbedding` | function | The deterministic unit vector Titan answers with. |
267
+ | `lexicalEmbedding`, `EMBEDDING_MODES` | function, array | The opt-in similarity-preserving embedding and the `embeddingMode` values. |
216
268
  | `sampleSchema` | function | The minimal instance of a JSON Schema (the unscripted structured output). |
217
269
  | `parseScript` | function | Validate one script (what `PUT /__admin/scripts` runs). |
218
270
  | `MODEL_OPERATIONS`, `STOP_REASONS`, `TURN_FAULTS` | arrays | The values `operation`, `stopReason` and `fault` accept. |
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createRuntime,
3
3
  parseScript
4
- } from "./chunk-UU3IC2CF.js";
4
+ } from "./chunk-PFSY7JLL.js";
5
5
 
6
6
  // src/h2c.ts
7
7
  import {
@@ -12,7 +12,6 @@ import {
12
12
  constants as http2Constants
13
13
  } from "node:http2";
14
14
  import { connect, createServer as createNetServer } from "node:net";
15
- import { Readable } from "node:stream";
16
15
  var PREFACE = "PRI * HTTP/2.0";
17
16
  var CONNECTION_HEADERS = /* @__PURE__ */ new Set([
18
17
  "connection",
@@ -22,7 +21,48 @@ var CONNECTION_HEADERS = /* @__PURE__ */ new Set([
22
21
  "upgrade",
23
22
  "host"
24
23
  ]);
25
- var toWebBody = (stream) => Readable.toWeb(stream);
24
+ var toWebBody = (stream) => {
25
+ let finished = false;
26
+ const detach = () => {
27
+ stream.off("data", onData);
28
+ stream.off("end", onEnd);
29
+ stream.off("error", onError);
30
+ stream.off("close", onClose);
31
+ };
32
+ let controller;
33
+ const settle = (action) => {
34
+ if (finished) return;
35
+ finished = true;
36
+ detach();
37
+ action();
38
+ };
39
+ const onData = (chunk) => {
40
+ if (finished) return;
41
+ controller.enqueue(
42
+ typeof chunk === "string" ? new TextEncoder().encode(chunk) : new Uint8Array(chunk)
43
+ );
44
+ if ((controller.desiredSize ?? 1) <= 0) stream.pause();
45
+ };
46
+ const onEnd = () => settle(() => controller.close());
47
+ const onError = (error) => settle(() => controller.error(error));
48
+ const onClose = () => settle(() => controller.error(new Error("request stream closed early")));
49
+ return new ReadableStream({
50
+ start(c) {
51
+ controller = c;
52
+ stream.on("data", onData);
53
+ stream.on("end", onEnd);
54
+ stream.on("error", onError);
55
+ stream.on("close", onClose);
56
+ },
57
+ pull() {
58
+ stream.resume();
59
+ },
60
+ cancel() {
61
+ settle(() => void 0);
62
+ stream.resume();
63
+ }
64
+ });
65
+ };
26
66
  var isDrop = (error) => error?.code === "MOCKINGBIRD_DROP";
27
67
  var internalError = (error) => JSON.stringify({
28
68
  error: {
@@ -298,4 +338,4 @@ export {
298
338
  createServer,
299
339
  serveTarget
300
340
  };
301
- //# sourceMappingURL=chunk-CHZFUB2R.js.map
341
+ //# sourceMappingURL=chunk-CL6K2ZUM.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/h2c.ts", "../src/server.ts"],
4
+ "sourcesContent": ["/// <reference types=\"node\" />\n/**\n * One port that speaks both cleartext HTTP/2 (prior knowledge, \"h2c\") and HTTP/1.1.\n *\n * AWS SDK v3 clients for Bedrock Runtime, Polly and Transcribe Streaming default to\n * `NodeHttp2Handler`, so against an `http://` endpoint they open an h2c connection and\n * send the HTTP/2 connection preface straight away; bidirectional operations (Nova Sonic,\n * `StartSpeechSynthesisStream`, `StartStreamTranscription`) need HTTP/2 duplex. The AI SDK,\n * AgentCore and Transcribe batch clients speak HTTP/1.1. A front `node:net` server reads\n * the first bytes of each connection and hands it to an internal HTTP/2 or HTTP/1.1\n * server; both turn requests into Fetch `Request`s whose bodies stream in as they arrive,\n * and stream responses back chunk by chunk.\n */\nimport {\n createServer as createHttp1Server,\n type IncomingMessage,\n type ServerResponse,\n} from \"node:http\"\nimport {\n createServer as createHttp2Server,\n constants as http2Constants,\n type IncomingHttpHeaders,\n type ServerHttp2Stream,\n} from \"node:http2\"\nimport { type AddressInfo, connect, createServer as createNetServer, type Socket } from \"node:net\"\nimport type { Readable } from \"node:stream\"\nimport type { FetchAPI } from \"@crvouga/mockingbird-core\"\n\nexport type H2cListenOptions = {\n /** Default `0`: the OS picks a free port. */\n port?: number\n /** Default `127.0.0.1`. */\n host?: string\n}\n\n/** A running dual-protocol listener. */\nexport type H2cListening = {\n url: string\n port: number\n host: string\n close(): Promise<void>\n}\n\nconst PREFACE = \"PRI * HTTP/2.0\"\n\n/** Headers HTTP/2 forbids on a response (RFC 9113 \u00A78.2.2). */\nconst CONNECTION_HEADERS = new Set([\n \"connection\",\n \"keep-alive\",\n \"proxy-connection\",\n \"transfer-encoding\",\n \"upgrade\",\n \"host\",\n])\n\n/**\n * A Fetch request body fed from a Node readable's `data`/`end` events. `Readable.toWeb()`\n * on an HTTP/2 server stream never closes on Node 22, so the body never ends and the\n * handler hangs; the events fire on every runtime. `pause`/`resume` carry backpressure.\n */\nconst toWebBody = (stream: Readable): ReadableStream<Uint8Array> => {\n let finished = false\n const detach = () => {\n stream.off(\"data\", onData)\n stream.off(\"end\", onEnd)\n stream.off(\"error\", onError)\n stream.off(\"close\", onClose)\n }\n let controller!: ReadableStreamDefaultController<Uint8Array>\n const settle = (action: () => void) => {\n if (finished) return\n finished = true\n detach()\n action()\n }\n const onData = (chunk: Buffer | string) => {\n if (finished) return\n controller.enqueue(\n typeof chunk === \"string\" ? new TextEncoder().encode(chunk) : new Uint8Array(chunk),\n )\n if ((controller.desiredSize ?? 1) <= 0) stream.pause()\n }\n const onEnd = () => settle(() => controller.close())\n const onError = (error: Error) => settle(() => controller.error(error))\n // A stream torn down before `end` (client reset) must not leave the reader waiting forever.\n const onClose = () => settle(() => controller.error(new Error(\"request stream closed early\")))\n return new ReadableStream<Uint8Array>({\n start(c) {\n controller = c\n stream.on(\"data\", onData)\n stream.on(\"end\", onEnd)\n stream.on(\"error\", onError)\n stream.on(\"close\", onClose)\n },\n pull() {\n stream.resume()\n },\n cancel() {\n settle(() => undefined)\n stream.resume()\n },\n })\n}\n\nconst isDrop = (error: unknown) => (error as { code?: string } | null)?.code === \"MOCKINGBIRD_DROP\"\n\nconst internalError = (error: unknown) =>\n JSON.stringify({\n error: {\n type: \"mockingbird_internal\",\n message: error instanceof Error ? error.message : String(error),\n },\n })\n\n/** Write a Fetch response body to a Node writable, respecting backpressure. */\nconst pump = async (\n body: ReadableStream<Uint8Array>,\n write: (chunk: Uint8Array) => boolean,\n drained: () => Promise<void>,\n closed: () => boolean,\n): Promise<void> => {\n const reader = body.getReader()\n try {\n for (;;) {\n if (closed()) {\n await reader.cancel().catch(() => undefined)\n return\n }\n const { done, value } = await reader.read()\n if (done) return\n if (!write(value)) await drained()\n }\n } finally {\n reader.releaseLock()\n }\n}\n\nconst handleHttp1 = async (\n api: FetchAPI,\n base: string,\n req: IncomingMessage,\n res: ServerResponse,\n): Promise<void> => {\n const method = req.method ?? \"GET\"\n const url = new URL((req.url ?? \"/\").replace(/^\\/+/, \"/\"), `http://${req.headers.host ?? base}`)\n const headers = new Headers()\n for (const [name, value] of Object.entries(req.headers)) {\n if (value === undefined) continue\n for (const each of Array.isArray(value) ? value : [value]) headers.append(name, each)\n }\n const aborted = new AbortController()\n res.once(\"close\", () => {\n if (!res.writableFinished) aborted.abort()\n })\n const hasBody = method !== \"GET\" && method !== \"HEAD\"\n const request = new Request(url, {\n method,\n headers,\n signal: aborted.signal,\n ...(hasBody ? { body: toWebBody(req), duplex: \"half\" } : {}),\n } as RequestInit)\n let response: Response\n try {\n response = await api.fetch(request)\n } catch (error) {\n if (isDrop(error)) {\n req.socket.destroy()\n return\n }\n res.writeHead(500, { \"content-type\": \"application/json\" })\n res.end(internalError(error))\n return\n }\n const out: Record<string, string | string[]> = Object.fromEntries(response.headers)\n const cookies = response.headers.getSetCookie()\n if (cookies.length > 0) out[\"set-cookie\"] = cookies\n res.writeHead(response.status, out)\n if (!response.body) {\n res.end()\n return\n }\n res.flushHeaders()\n try {\n await pump(\n response.body,\n (chunk) => res.write(chunk),\n () => new Promise((resolve) => res.once(\"drain\", resolve)),\n () => res.destroyed,\n )\n res.end()\n } catch {\n res.destroy()\n }\n}\n\nconst handleHttp2 = async (\n api: FetchAPI,\n base: string,\n stream: ServerHttp2Stream,\n incoming: IncomingHttpHeaders,\n): Promise<void> => {\n const method = String(incoming[\":method\"] ?? \"GET\")\n const authority = String(incoming[\":authority\"] ?? incoming.host ?? base)\n const url = new URL(String(incoming[\":path\"] ?? \"/\").replace(/^\\/+/, \"/\"), `http://${authority}`)\n const headers = new Headers()\n for (const [name, value] of Object.entries(incoming)) {\n if (name.startsWith(\":\") || value === undefined) continue\n for (const each of Array.isArray(value) ? value : [value]) headers.append(name, String(each))\n }\n const aborted = new AbortController()\n stream.once(\"close\", () => {\n if (!stream.writableFinished) aborted.abort()\n })\n stream.on(\"error\", () => undefined)\n const hasBody = method !== \"GET\" && method !== \"HEAD\"\n const request = new Request(url, {\n method,\n headers,\n signal: aborted.signal,\n ...(hasBody ? { body: toWebBody(stream), duplex: \"half\" } : {}),\n } as RequestInit)\n let response: Response\n try {\n response = await api.fetch(request)\n } catch (error) {\n if (isDrop(error)) {\n stream.close(http2Constants.NGHTTP2_INTERNAL_ERROR)\n return\n }\n if (stream.destroyed) return\n stream.respond({ \":status\": 500, \"content-type\": \"application/json\" })\n stream.end(internalError(error))\n return\n }\n if (stream.destroyed || stream.closed) return\n const out: Record<string, string | string[] | number> = { \":status\": response.status }\n for (const [name, value] of response.headers) {\n if (!CONNECTION_HEADERS.has(name)) out[name] = value\n }\n if (!response.body) {\n stream.respond(out, { endStream: true })\n return\n }\n stream.respond(out)\n try {\n await pump(\n response.body,\n (chunk) => stream.write(chunk),\n () => new Promise((resolve) => stream.once(\"drain\", resolve)),\n () => stream.destroyed || stream.closed,\n )\n if (!stream.destroyed) stream.end()\n } catch {\n if (!stream.destroyed) stream.close(http2Constants.NGHTTP2_INTERNAL_ERROR)\n }\n}\n\nconst listenInternal = (server: {\n listen: (...args: unknown[]) => unknown\n once: (...args: never[]) => unknown\n address(): AddressInfo | string | null\n}) =>\n new Promise<number>((resolve, reject) => {\n ;(server.once as (event: string, listener: (error: Error) => void) => void)(\"error\", reject)\n server.listen(0, \"127.0.0.1\", () => resolve((server.address() as AddressInfo).port))\n })\n\n/**\n * Serve `api` over h2c and HTTP/1.1 on one port. Each accepted connection is sniffed for\n * the HTTP/2 preface and relayed to an internal loopback server for that protocol.\n */\nexport const listenH2c = async (\n api: FetchAPI,\n options: H2cListenOptions = {},\n): Promise<H2cListening> => {\n const host = options.host ?? \"127.0.0.1\"\n const shown = host.includes(\":\") ? `[${host}]` : host\n let base = `${shown}:${options.port ?? 0}`\n const h1 = createHttp1Server((req, res) => {\n void handleHttp1(api, base, req, res)\n })\n const h2 = createHttp2Server()\n h2.on(\"stream\", (stream, headers) => {\n void handleHttp2(api, base, stream, headers)\n })\n h2.on(\"sessionError\", () => undefined)\n const h1Port = await listenInternal(h1 as never)\n const h2Port = await listenInternal(h2 as never)\n const sockets = new Set<Socket>()\n const track = (socket: Socket) => {\n sockets.add(socket)\n socket.once(\"close\", () => sockets.delete(socket))\n }\n const front = createNetServer((socket) => {\n track(socket)\n socket.setNoDelay(true)\n let seen = Buffer.alloc(0)\n const onData = (chunk: Buffer) => {\n seen = Buffer.concat([seen, chunk])\n // \"PRI\" opens only the HTTP/2 preface; no HTTP/1.1 method starts that way.\n if (seen.length < 3) return\n socket.off(\"data\", onData)\n socket.pause()\n const http2 = seen.subarray(0, 3).toString(\"latin1\") === PREFACE.slice(0, 3)\n const upstream = connect(http2 ? h2Port : h1Port, \"127.0.0.1\")\n track(upstream)\n upstream.setNoDelay(true)\n const destroy = () => {\n socket.destroy()\n upstream.destroy()\n }\n socket.on(\"error\", destroy)\n upstream.on(\"error\", destroy)\n socket.once(\"close\", () => upstream.destroy())\n upstream.once(\"close\", () => socket.destroy())\n upstream.write(seen)\n socket.pipe(upstream)\n upstream.pipe(socket)\n socket.resume()\n }\n socket.on(\"data\", onData)\n socket.on(\"error\", () => socket.destroy())\n })\n await new Promise<void>((resolve, reject) => {\n front.once(\"error\", reject)\n front.listen(options.port ?? 0, host, () => resolve())\n })\n const port = (front.address() as AddressInfo).port\n base = `${shown}:${port}`\n const closeServer = (server: { close: (cb: (error?: Error) => void) => unknown }) =>\n new Promise<void>((resolve) => {\n server.close(() => resolve())\n })\n return {\n url: `http://${shown}:${port}`,\n port,\n host,\n close: async () => {\n const closing = [\n closeServer(front as never),\n closeServer(h1 as never),\n closeServer(h2 as never),\n ]\n for (const socket of sockets) socket.destroy()\n h1.closeAllConnections?.()\n await Promise.all(closing)\n },\n }\n}\n", "/// <reference types=\"node\" />\nimport type { ServeTarget } from \"@crvouga/mockingbird-adapter-node\"\nimport { type H2cListening, listenH2c } from \"./h2c.js\"\nimport { type BedrockRuntime, type BedrockRuntimeOptions, createRuntime } from \"./runtime.js\"\nimport { parseScript, type Script } from \"./scripts.js\"\n\n/** Port `mockingbird-bedrock serve` listens on when none is given. */\nexport const DEFAULT_PORT = 8796\n\nexport type BedrockServerOptions = BedrockRuntimeOptions & {\n /** Default `0`: the OS picks a free port. */\n port?: number\n /** Default `127.0.0.1`. */\n host?: string\n}\n\nexport type BedrockServer = H2cListening & { runtime: BedrockRuntime }\n\n/**\n * Serve the Bedrock mock on one port that speaks both h2c (the AWS SDK's default\n * `NodeHttp2Handler`, and Nova Sonic's duplex stream) and HTTP/1.1 (the AI SDK, AgentCore).\n */\nexport const createServer = async (options: BedrockServerOptions = {}): Promise<BedrockServer> => {\n const { port, host, ...rest } = options\n const runtime = createRuntime(rest)\n const listening = await listenH2c(runtime, {\n port: port ?? 0,\n ...(host !== undefined ? { host } : {}),\n })\n return { ...listening, runtime }\n}\n\nconst text = (value: string | boolean | undefined) =>\n typeof value === \"string\" ? value : undefined\n\n/** Scripts from `--scripts <file.json>` (Node only). */\nconst loadScripts = async (path: string): Promise<Script[]> => {\n const { readFile } = await import(\"node:fs/promises\")\n const raw = JSON.parse(await readFile(path, \"utf8\")) as unknown\n const list = Array.isArray(raw) ? raw : (raw as { scripts?: unknown[] }).scripts\n if (!Array.isArray(list)) throw new Error(`${path}: expected {\"scripts\": [...]}`)\n return list.map((each, index) => {\n const parsed = parseScript(each, index)\n if (typeof parsed === \"string\") throw new Error(`${path}: ${parsed}`)\n return parsed\n })\n}\n\n/**\n * How `serve` builds the Bedrock mock from flags. `serve --config` in another service's CLI\n * listens over HTTP/1.1 only; `mockingbird-bedrock serve` listens with h2c as well.\n */\nexport const serveTarget: ServeTarget = {\n name: \"bedrock\",\n defaultPort: DEFAULT_PORT,\n options: {\n scripts: {\n type: \"string\",\n value: \"<file.json>\",\n description:\n 'Scripts every namespace starts with ({\"scripts\": [...]}, as PUT /__admin/scripts)',\n },\n \"default-text\": {\n type: \"string\",\n value: \"<text>\",\n description: 'What an unscripted chat call answers (default \"OK.\")',\n },\n },\n create: async (values, common) => {\n const scriptsPath = text(values.scripts)\n const defaultText = text(values[\"default-text\"])\n return createRuntime({\n ...(scriptsPath ? { scripts: await loadScripts(scriptsPath) } : {}),\n ...(defaultText !== undefined ? { settings: { defaultText } } : {}),\n ...(common.adminPrefix !== undefined ? { adminPrefix: common.adminPrefix } : {}),\n ...(common.adminKey !== undefined ? { adminKey: common.adminKey } : {}),\n ...(common.adminControls !== undefined ? { adminControls: common.adminControls } : {}),\n ...(common.seed !== undefined ? { seed: common.seed } : {}),\n ...(common.onLog ? { onLog: common.onLog } : {}),\n }) as never\n },\n banner: () => [\n \"point the app at it: AWS_ENDPOINT_URL_BEDROCK_RUNTIME / AWS_ENDPOINT_URL_BEDROCK_AGENTCORE = this URL\",\n \"protocols: h2c (prior knowledge) and HTTP/1.1 on the same port\",\n \"namespaces: x-mockingbird-namespace, /__admin/ns/<name>/\u2026, or PUT /__admin/credentials {<AWS_ACCESS_KEY_ID>: <ns>}\",\n \"scripts: PUT /__admin/scripts {scripts: [{id, match, turns}]}\",\n ],\n}\n\nexport type { H2cListening, H2cListenOptions } from \"./h2c.js\"\nexport { listenH2c } from \"./h2c.js\"\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }