@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 +18 -1
- package/README.md +57 -5
- package/dist/{chunk-CHZFUB2R.js → chunk-CL6K2ZUM.js} +44 -4
- package/dist/chunk-CL6K2ZUM.js.map +7 -0
- package/dist/{chunk-UU3IC2CF.js → chunk-PFSY7JLL.js} +317 -51
- package/dist/chunk-PFSY7JLL.js.map +7 -0
- package/dist/cli.js +115 -15
- package/dist/cli.js.map +3 -3
- package/dist/index.d.ts +64 -3
- package/dist/index.js +5 -1
- package/dist/server.d.ts +97 -1
- package/dist/server.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-CHZFUB2R.js.map +0 -7
- package/dist/chunk-UU3IC2CF.js.map +0 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
# Changelog — @crvouga/mockingbird-service-bedrock
|
|
2
2
|
|
|
3
|
-
## 3.
|
|
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
|
|
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`), `
|
|
131
|
-
`
|
|
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-
|
|
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) =>
|
|
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-
|
|
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
|
+
}
|