@crvouga/mockingbird-service-bedrock 0.2.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -1
- package/README.md +1 -1
- package/dist/{chunk-BMGWOFIJ.js → chunk-DN5K7HCG.js} +2 -2
- package/dist/{chunk-O5ZO5KMR.js → chunk-QUUSPEWJ.js} +97 -25
- package/dist/chunk-QUUSPEWJ.js.map +7 -0
- package/dist/cli.js +5 -3
- package/dist/cli.js.map +2 -2
- package/dist/index.d.ts +129 -101
- package/dist/index.js +1 -1
- package/dist/server.d.ts +233 -177
- package/dist/server.js +2 -2
- package/package.json +6 -2
- package/dist/chunk-O5ZO5KMR.js.map +0 -7
- /package/dist/{chunk-BMGWOFIJ.js.map → chunk-DN5K7HCG.js.map} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
# Changelog — @crvouga/mockingbird-service-bedrock
|
|
2
2
|
|
|
3
|
-
## 0.
|
|
3
|
+
## 1.0.1 (2026-09-26)
|
|
4
|
+
|
|
5
|
+
### Fixes and improvements
|
|
6
|
+
|
|
7
|
+
- take the rejected-request byte count from content-length, never by reading the body ([a0e5fb2](https://github.com/crvouga/mockingbird/commit/a0e5fb2fc80ab725c3552b612f3f091fd6c857fb))
|
|
8
|
+
- reject a present body by media type, and log what a rejected request sent ([12e351a](https://github.com/crvouga/mockingbird/commit/12e351aba53cfb7b41e31a7809419455fc2902eb))
|
|
9
|
+
|
|
10
|
+
## 1.0.0 (2026-09-24)
|
|
11
|
+
|
|
12
|
+
### ⚠️ Breaking changes
|
|
13
|
+
|
|
14
|
+
- vendor branding for every service; purge internal mocks and consumer names ([f689534](https://github.com/crvouga/mockingbird/commit/f6895343543550dafcb7d76b426cae7635e03226))
|
|
15
|
+
|
|
16
|
+
## 0.2.0 (2026-09-23)
|
|
4
17
|
|
|
5
18
|
### Features
|
|
6
19
|
|
package/README.md
CHANGED
|
@@ -115,7 +115,7 @@ how many calls it answers.
|
|
|
115
115
|
(`true` or `{text, trace}`: `guardrail_intervened` with Bedrock's refusal text and a trace),
|
|
116
116
|
`toolResult` (harness), `userTranscript` (Nova Sonic), `stopReason`, `usage`, `fault`.
|
|
117
117
|
- **Structured output** (`json`) goes out as text JSON for
|
|
118
|
-
`outputConfig.textFormat.structure.jsonSchema` (
|
|
118
|
+
`outputConfig.textFormat.structure.jsonSchema` (Python boto3 clients) and
|
|
119
119
|
`additionalModelRequestFields.output_config.format` (AI SDK native), and as a `toolUse` of the
|
|
120
120
|
forced tool for `toolChoice: {tool}` or `{any}` (the AI SDK's synthetic `json` tool, insight
|
|
121
121
|
reports' `record_chat_*`).
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createRuntime,
|
|
3
3
|
parseScript
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-QUUSPEWJ.js";
|
|
5
5
|
|
|
6
6
|
// src/h2c.ts
|
|
7
7
|
import {
|
|
@@ -296,4 +296,4 @@ export {
|
|
|
296
296
|
createServer,
|
|
297
297
|
serveTarget
|
|
298
298
|
};
|
|
299
|
-
//# sourceMappingURL=chunk-
|
|
299
|
+
//# sourceMappingURL=chunk-DN5K7HCG.js.map
|
|
@@ -1367,6 +1367,90 @@ var operationMetadata = (operation) => {
|
|
|
1367
1367
|
|
|
1368
1368
|
// ../core/dist/service.js
|
|
1369
1369
|
import { Hono } from "hono";
|
|
1370
|
+
|
|
1371
|
+
// ../core/dist/validation.js
|
|
1372
|
+
var requestBodyOf = (context) => {
|
|
1373
|
+
const requestBody = context.operation.operation.requestBody;
|
|
1374
|
+
return requestBody ? deref(context.document, requestBody) : void 0;
|
|
1375
|
+
};
|
|
1376
|
+
var mediaTypeMatches = (accepted, actual) => {
|
|
1377
|
+
const pattern = mediaTypeOf(accepted) ?? accepted.toLowerCase();
|
|
1378
|
+
if (pattern === actual || pattern === "*/*")
|
|
1379
|
+
return true;
|
|
1380
|
+
const [type, subtype] = pattern.split("/");
|
|
1381
|
+
const [actualType, actualSubtype] = actual.split("/");
|
|
1382
|
+
if (type !== actualType && type !== "*")
|
|
1383
|
+
return false;
|
|
1384
|
+
if (subtype === void 0 || subtype === "*")
|
|
1385
|
+
return true;
|
|
1386
|
+
if (subtype.startsWith("*+"))
|
|
1387
|
+
return actualSubtype?.endsWith(subtype.slice(1)) === true;
|
|
1388
|
+
return false;
|
|
1389
|
+
};
|
|
1390
|
+
var acceptedKeyFor = (content, mediaType) => {
|
|
1391
|
+
if (!content || mediaType === void 0)
|
|
1392
|
+
return void 0;
|
|
1393
|
+
const keys = Object.keys(content);
|
|
1394
|
+
return keys.find((key) => mediaTypeOf(key) === mediaType) ?? keys.find((key) => mediaTypeMatches(key, mediaType));
|
|
1395
|
+
};
|
|
1396
|
+
var unsupportedMediaType = (context, options = {}) => {
|
|
1397
|
+
if (context.body.kind === "empty" && options.includeEmpty !== true)
|
|
1398
|
+
return void 0;
|
|
1399
|
+
const content = requestBodyOf(context)?.content;
|
|
1400
|
+
if (!content || Object.keys(content).length === 0)
|
|
1401
|
+
return void 0;
|
|
1402
|
+
const mediaType = mediaTypeOf(context.request.headers.get("content-type"));
|
|
1403
|
+
if (acceptedKeyFor(content, mediaType) !== void 0)
|
|
1404
|
+
return void 0;
|
|
1405
|
+
return { mediaType: mediaType ?? null, accepted: Object.keys(content) };
|
|
1406
|
+
};
|
|
1407
|
+
var recorded = /* @__PURE__ */ new WeakMap();
|
|
1408
|
+
var recordedIssues = (request) => recorded.get(request);
|
|
1409
|
+
var bodyIssues = (context, contentType = "application/json") => {
|
|
1410
|
+
const issues = findBodyIssues(context, contentType);
|
|
1411
|
+
if (issues.length > 0)
|
|
1412
|
+
recorded.set(context.request, issues);
|
|
1413
|
+
return issues;
|
|
1414
|
+
};
|
|
1415
|
+
var findBodyIssues = (context, contentType) => {
|
|
1416
|
+
const resolved = requestBodyOf(context);
|
|
1417
|
+
if (!resolved)
|
|
1418
|
+
return [];
|
|
1419
|
+
const unsupported = unsupportedMediaType(context);
|
|
1420
|
+
if (unsupported) {
|
|
1421
|
+
return [
|
|
1422
|
+
{
|
|
1423
|
+
path: "",
|
|
1424
|
+
kind: "media_type",
|
|
1425
|
+
message: unsupported.mediaType === null ? "request body has no content-type" : `request body media type ${unsupported.mediaType} is not supported`
|
|
1426
|
+
}
|
|
1427
|
+
];
|
|
1428
|
+
}
|
|
1429
|
+
const key = acceptedKeyFor(resolved.content, mediaTypeOf(context.request.headers.get("content-type"))) ?? contentType;
|
|
1430
|
+
const schema = resolved.content?.[key]?.schema;
|
|
1431
|
+
if (!schema)
|
|
1432
|
+
return [];
|
|
1433
|
+
if (context.body.kind === "invalid") {
|
|
1434
|
+
return [
|
|
1435
|
+
{
|
|
1436
|
+
path: "",
|
|
1437
|
+
kind: "syntax",
|
|
1438
|
+
message: `request body is not valid ${context.body.mediaType}`
|
|
1439
|
+
}
|
|
1440
|
+
];
|
|
1441
|
+
}
|
|
1442
|
+
const value = context.body.kind === "json" || context.body.kind === "form" || context.body.kind === "text" ? context.body.value : void 0;
|
|
1443
|
+
if (value === void 0) {
|
|
1444
|
+
return resolved.required && context.body.kind === "empty" ? [{ path: "", kind: "required", message: "request body is required" }] : [];
|
|
1445
|
+
}
|
|
1446
|
+
return validateValue(context.document, resolveSchema(context.document, schema), value).map((issue) => ({ path: issue.path.join("."), kind: "schema", message: issue.message }));
|
|
1447
|
+
};
|
|
1448
|
+
|
|
1449
|
+
// ../core/dist/service.js
|
|
1450
|
+
var withIssues = (request, response) => {
|
|
1451
|
+
const issues = response.status >= 400 ? recordedIssues(request) : void 0;
|
|
1452
|
+
return issues && issues.length > 0 ? annotateResponse(response, { issues }) : response;
|
|
1453
|
+
};
|
|
1370
1454
|
var defineOperations = (handlers) => handlers;
|
|
1371
1455
|
var OperationRegistryError = class extends Error {
|
|
1372
1456
|
problems;
|
|
@@ -1452,9 +1536,7 @@ var createService = (options) => {
|
|
|
1452
1536
|
now
|
|
1453
1537
|
};
|
|
1454
1538
|
const short = await options.before?.(context);
|
|
1455
|
-
|
|
1456
|
-
return short;
|
|
1457
|
-
return handler(context);
|
|
1539
|
+
return withIssues(request, short ?? await handler(context));
|
|
1458
1540
|
};
|
|
1459
1541
|
app.on(operation.method.toUpperCase(), honoPath(operation.path), route);
|
|
1460
1542
|
}
|
|
@@ -1491,7 +1573,7 @@ var restoreNamespace = (sqlite, namespace, snapshot) => {
|
|
|
1491
1573
|
};
|
|
1492
1574
|
|
|
1493
1575
|
// ../core/dist/version.js
|
|
1494
|
-
var PACKAGE_VERSION = true ? "0.
|
|
1576
|
+
var PACKAGE_VERSION = true ? "1.0.1" : UNRELEASED_VERSION;
|
|
1495
1577
|
|
|
1496
1578
|
// ../core/dist/signing.js
|
|
1497
1579
|
var encoder = new TextEncoder();
|
|
@@ -1936,8 +2018,15 @@ var createRuntime = (options) => {
|
|
|
1936
2018
|
const started = monotonicNow();
|
|
1937
2019
|
const url = new URL(request.url);
|
|
1938
2020
|
const operationId = operationIdFor(request, url.pathname);
|
|
2021
|
+
const contentLength = request.headers.get("content-length");
|
|
2022
|
+
const received = {
|
|
2023
|
+
contentType: request.headers.get("content-type"),
|
|
2024
|
+
bodyBytes: contentLength !== null && /^\d+$/.test(contentLength) ? Number(contentLength) : null,
|
|
2025
|
+
transferEncoding: request.headers.get("transfer-encoding")
|
|
2026
|
+
};
|
|
1939
2027
|
const log = (status, faultId, response2) => {
|
|
1940
2028
|
const noted = response2 ? responseNotes(response2) : void 0;
|
|
2029
|
+
const rejected = status >= 400 && faultId === void 0;
|
|
1941
2030
|
const entry = {
|
|
1942
2031
|
service: options.name,
|
|
1943
2032
|
namespace,
|
|
@@ -1949,7 +2038,9 @@ var createRuntime = (options) => {
|
|
|
1949
2038
|
unmatched: options.document !== void 0 && operationId === void 0,
|
|
1950
2039
|
...faultId !== void 0 ? { faultId } : {},
|
|
1951
2040
|
...noted?.ids && Object.keys(noted.ids).length > 0 ? { ids: noted.ids } : {},
|
|
1952
|
-
...noted?.adopted ? { adopted: true } : {}
|
|
2041
|
+
...noted?.adopted ? { adopted: true } : {},
|
|
2042
|
+
...rejected ? { request: { ...received } } : {},
|
|
2043
|
+
...rejected && noted?.issues && noted.issues.length > 0 ? { issues: noted.issues.map((issue) => ({ ...issue })) } : {}
|
|
1953
2044
|
};
|
|
1954
2045
|
metrics.record(entry);
|
|
1955
2046
|
journal.record({ ...entry, at: new Date(clock.now()).toISOString() });
|
|
@@ -2156,25 +2247,6 @@ var presetRoutes = (presets, runtime) => ({
|
|
|
2156
2247
|
}
|
|
2157
2248
|
});
|
|
2158
2249
|
|
|
2159
|
-
// ../core/dist/validation.js
|
|
2160
|
-
var bodyIssues = (context, contentType = "application/json") => {
|
|
2161
|
-
const requestBody = context.operation.operation.requestBody;
|
|
2162
|
-
if (!requestBody)
|
|
2163
|
-
return [];
|
|
2164
|
-
const resolved = deref(context.document, requestBody);
|
|
2165
|
-
const schema = resolved.content?.[contentType]?.schema;
|
|
2166
|
-
if (!schema)
|
|
2167
|
-
return [];
|
|
2168
|
-
const value = context.body.kind === "json" || context.body.kind === "form" ? context.body.value : void 0;
|
|
2169
|
-
if (context.body.kind === "invalid") {
|
|
2170
|
-
return [{ path: "", message: `request body is not valid ${context.body.mediaType}` }];
|
|
2171
|
-
}
|
|
2172
|
-
if (value === void 0) {
|
|
2173
|
-
return resolved.required ? [{ path: "", message: "request body is required" }] : [];
|
|
2174
|
-
}
|
|
2175
|
-
return validateValue(context.document, resolveSchema(context.document, schema), value).map((issue) => ({ path: issue.path.join("."), message: issue.message }));
|
|
2176
|
-
};
|
|
2177
|
-
|
|
2178
2250
|
// src/analyze.ts
|
|
2179
2251
|
var isRecord4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2180
2252
|
var array = (value) => Array.isArray(value) ? value : [];
|
|
@@ -4638,4 +4710,4 @@ export {
|
|
|
4638
4710
|
titanEmbedding,
|
|
4639
4711
|
BedrockAPI
|
|
4640
4712
|
};
|
|
4641
|
-
//# sourceMappingURL=chunk-
|
|
4713
|
+
//# sourceMappingURL=chunk-QUUSPEWJ.js.map
|