la-machina-engine 0.14.0 → 0.15.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/dist/index.cjs +108 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +34 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.js +108 -8
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1271,6 +1271,21 @@ var ApiEndpointSchema = import_zod.z.object({
|
|
|
1271
1271
|
inputSchema: import_zod.z.unknown().optional(),
|
|
1272
1272
|
outputHint: import_zod.z.string().optional()
|
|
1273
1273
|
}).strict();
|
|
1274
|
+
var HEADER_NAME_RE = /^[!#$%&'*+\-.0-9A-Z^_`a-z|~]+$/;
|
|
1275
|
+
var RESERVED_HEADER_NAMES = /* @__PURE__ */ new Set([
|
|
1276
|
+
"authorization",
|
|
1277
|
+
"cookie",
|
|
1278
|
+
"set-cookie",
|
|
1279
|
+
"proxy-authorization"
|
|
1280
|
+
]);
|
|
1281
|
+
var SECRET_PATTERN_RE = /(-secret|-token|-key)$/i;
|
|
1282
|
+
var RESERVED_DEFAULT_HEADER_EXACT = /* @__PURE__ */ new Set([
|
|
1283
|
+
"authorization",
|
|
1284
|
+
"cookie",
|
|
1285
|
+
"set-cookie",
|
|
1286
|
+
"proxy-authorization",
|
|
1287
|
+
"x-auth-token"
|
|
1288
|
+
]);
|
|
1274
1289
|
var ApiServiceSchema = import_zod.z.object({
|
|
1275
1290
|
name: import_zod.z.string().min(1),
|
|
1276
1291
|
description: import_zod.z.string().optional(),
|
|
@@ -1282,8 +1297,67 @@ var ApiServiceSchema = import_zod.z.object({
|
|
|
1282
1297
|
allowedMethods: import_zod.z.array(ApiHttpMethodEnum).optional(),
|
|
1283
1298
|
defaultHeaders: import_zod.z.record(import_zod.z.string(), import_zod.z.string()).optional(),
|
|
1284
1299
|
maxBodyBytes: import_zod.z.number().int().positive().optional(),
|
|
1285
|
-
endpoints: import_zod.z.array(ApiEndpointSchema).optional()
|
|
1286
|
-
|
|
1300
|
+
endpoints: import_zod.z.array(ApiEndpointSchema).optional(),
|
|
1301
|
+
secretHeaders: import_zod.z.record(import_zod.z.string(), import_zod.z.string().min(1)).optional()
|
|
1302
|
+
}).strict().superRefine((svc, ctx) => {
|
|
1303
|
+
if (svc.defaultHeaders !== void 0) {
|
|
1304
|
+
for (const headerName of Object.keys(svc.defaultHeaders)) {
|
|
1305
|
+
if (!HEADER_NAME_RE.test(headerName)) {
|
|
1306
|
+
ctx.addIssue({
|
|
1307
|
+
code: "custom",
|
|
1308
|
+
message: `defaultHeaders key "${headerName}" is not a valid HTTP header name (RFC 7230 token charset)`,
|
|
1309
|
+
path: ["defaultHeaders", headerName]
|
|
1310
|
+
});
|
|
1311
|
+
continue;
|
|
1312
|
+
}
|
|
1313
|
+
const lower = headerName.toLowerCase();
|
|
1314
|
+
if (RESERVED_DEFAULT_HEADER_EXACT.has(lower)) {
|
|
1315
|
+
ctx.addIssue({
|
|
1316
|
+
code: "custom",
|
|
1317
|
+
message: `defaultHeaders key "${headerName}" is reserved \u2014 move secret-bearing values to secretHeaders or primary auth`,
|
|
1318
|
+
path: ["defaultHeaders", headerName]
|
|
1319
|
+
});
|
|
1320
|
+
continue;
|
|
1321
|
+
}
|
|
1322
|
+
if (SECRET_PATTERN_RE.test(headerName)) {
|
|
1323
|
+
ctx.addIssue({
|
|
1324
|
+
code: "custom",
|
|
1325
|
+
message: `defaultHeaders key "${headerName}" looks like a secret-bearing name (matches *-secret/*-token/*-key). Move to secretHeaders so the value is vault-resolved + scrubbed.`,
|
|
1326
|
+
path: ["defaultHeaders", headerName]
|
|
1327
|
+
});
|
|
1328
|
+
}
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
if (svc.secretHeaders === void 0) return;
|
|
1332
|
+
const lowerDefault = /* @__PURE__ */ new Set();
|
|
1333
|
+
for (const k of Object.keys(svc.defaultHeaders ?? {})) lowerDefault.add(k.toLowerCase());
|
|
1334
|
+
for (const headerName of Object.keys(svc.secretHeaders)) {
|
|
1335
|
+
if (!HEADER_NAME_RE.test(headerName)) {
|
|
1336
|
+
ctx.addIssue({
|
|
1337
|
+
code: "custom",
|
|
1338
|
+
message: `secretHeaders key "${headerName}" is not a valid HTTP header name (RFC 7230 token charset)`,
|
|
1339
|
+
path: ["secretHeaders", headerName]
|
|
1340
|
+
});
|
|
1341
|
+
continue;
|
|
1342
|
+
}
|
|
1343
|
+
const lower = headerName.toLowerCase();
|
|
1344
|
+
if (RESERVED_HEADER_NAMES.has(lower)) {
|
|
1345
|
+
ctx.addIssue({
|
|
1346
|
+
code: "custom",
|
|
1347
|
+
message: `secretHeaders key "${headerName}" is reserved \u2014 primary \`auth\` owns ${headerName}`,
|
|
1348
|
+
path: ["secretHeaders", headerName]
|
|
1349
|
+
});
|
|
1350
|
+
continue;
|
|
1351
|
+
}
|
|
1352
|
+
if (lowerDefault.has(lower)) {
|
|
1353
|
+
ctx.addIssue({
|
|
1354
|
+
code: "custom",
|
|
1355
|
+
message: `secretHeaders key "${headerName}" collides with defaultHeaders (case-insensitive). Move the secret-bearing version to secretHeaders only.`,
|
|
1356
|
+
path: ["secretHeaders", headerName]
|
|
1357
|
+
});
|
|
1358
|
+
}
|
|
1359
|
+
}
|
|
1360
|
+
});
|
|
1287
1361
|
var ApiCatalogModeEnum = import_zod.z.enum(["eager", "lazy", "auto"]);
|
|
1288
1362
|
var ApiConfigResolved = import_zod.z.object({
|
|
1289
1363
|
services: import_zod.z.array(ApiServiceSchema),
|
|
@@ -8380,6 +8454,12 @@ function createApiCallTool(opts) {
|
|
|
8380
8454
|
`createApiCallTool: service "${svc.name}" uses custom auth (id: ${svc.auth.id}) but no resolveAuth was supplied`
|
|
8381
8455
|
);
|
|
8382
8456
|
}
|
|
8457
|
+
const hasSecretHeaders = svc.secretHeaders !== void 0 && Object.keys(svc.secretHeaders).length > 0;
|
|
8458
|
+
if (hasSecretHeaders && opts.resolveAuth === void 0) {
|
|
8459
|
+
throw new Error(
|
|
8460
|
+
`createApiCallTool: service "${svc.name}" declares secretHeaders but no resolveAuth was supplied (the resolver is required to look up the secret values)`
|
|
8461
|
+
);
|
|
8462
|
+
}
|
|
8383
8463
|
}
|
|
8384
8464
|
const fetchFn = opts.fetch ?? globalThis.fetch.bind(globalThis);
|
|
8385
8465
|
const maxResponseBytes = opts.maxResponseBytes ?? DEFAULT_MAX_RESPONSE_BYTES;
|
|
@@ -8444,13 +8524,20 @@ function createApiCallTool(opts) {
|
|
|
8444
8524
|
return errResult(`ERR_API_BODY_TOO_LARGE: exceeds ${cap} bytes`);
|
|
8445
8525
|
}
|
|
8446
8526
|
}
|
|
8527
|
+
const secretHeaderRefs = svc.secretHeaders !== void 0 && Object.keys(svc.secretHeaders).length > 0 ? svc.secretHeaders : void 0;
|
|
8447
8528
|
let authHeaders;
|
|
8448
8529
|
try {
|
|
8449
8530
|
authHeaders = await resolveAuth({
|
|
8450
8531
|
auth: svc.auth ?? { type: "none" },
|
|
8451
8532
|
env: opts.env,
|
|
8452
8533
|
resolver: opts.resolveAuth,
|
|
8453
|
-
ctx: {
|
|
8534
|
+
ctx: {
|
|
8535
|
+
serviceName: svc.name,
|
|
8536
|
+
method: input.method,
|
|
8537
|
+
path: input.path,
|
|
8538
|
+
...secretHeaderRefs !== void 0 ? { secretHeaderRefs } : {}
|
|
8539
|
+
},
|
|
8540
|
+
forceResolve: secretHeaderRefs !== void 0
|
|
8454
8541
|
});
|
|
8455
8542
|
} catch (err) {
|
|
8456
8543
|
const raw2 = err instanceof Error ? err.message : String(err);
|
|
@@ -8559,22 +8646,27 @@ function sanitizeHeaders(user, auth) {
|
|
|
8559
8646
|
return out;
|
|
8560
8647
|
}
|
|
8561
8648
|
async function resolveAuth(args) {
|
|
8562
|
-
const { auth, env, resolver, ctx } = args;
|
|
8649
|
+
const { auth, env, resolver, ctx, forceResolve } = args;
|
|
8650
|
+
let primary;
|
|
8563
8651
|
switch (auth.type) {
|
|
8564
8652
|
case "none":
|
|
8565
|
-
|
|
8653
|
+
primary = {};
|
|
8654
|
+
break;
|
|
8566
8655
|
case "bearer": {
|
|
8567
8656
|
const token = envLookup(env, auth.tokenRef);
|
|
8568
|
-
|
|
8657
|
+
primary = { Authorization: `Bearer ${token}` };
|
|
8658
|
+
break;
|
|
8569
8659
|
}
|
|
8570
8660
|
case "header": {
|
|
8571
8661
|
const value = envLookup(env, auth.valueRef);
|
|
8572
|
-
|
|
8662
|
+
primary = { [auth.name]: value };
|
|
8663
|
+
break;
|
|
8573
8664
|
}
|
|
8574
8665
|
case "basic": {
|
|
8575
8666
|
const u = envLookup(env, auth.userRef);
|
|
8576
8667
|
const p = envLookup(env, auth.passRef);
|
|
8577
|
-
|
|
8668
|
+
primary = { Authorization: `Basic ${base64(`${u}:${p}`)}` };
|
|
8669
|
+
break;
|
|
8578
8670
|
}
|
|
8579
8671
|
case "custom":
|
|
8580
8672
|
if (resolver === void 0) {
|
|
@@ -8582,6 +8674,14 @@ async function resolveAuth(args) {
|
|
|
8582
8674
|
}
|
|
8583
8675
|
return resolver(auth, ctx);
|
|
8584
8676
|
}
|
|
8677
|
+
if (forceResolve === true) {
|
|
8678
|
+
if (resolver === void 0) {
|
|
8679
|
+
throw new Error("secretHeaders require a resolveAuth callback (host did not supply one)");
|
|
8680
|
+
}
|
|
8681
|
+
const extra = await resolver(auth, ctx);
|
|
8682
|
+
return { ...primary, ...extra };
|
|
8683
|
+
}
|
|
8684
|
+
return primary;
|
|
8585
8685
|
}
|
|
8586
8686
|
function envLookup(env, ref) {
|
|
8587
8687
|
if (env === void 0 || env[ref] === void 0) {
|