la-machina-engine 0.14.0 → 0.15.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/dist/index.cjs CHANGED
@@ -1271,6 +1271,13 @@ 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
+ ]);
1274
1281
  var ApiServiceSchema = import_zod.z.object({
1275
1282
  name: import_zod.z.string().min(1),
1276
1283
  description: import_zod.z.string().optional(),
@@ -1282,8 +1289,39 @@ var ApiServiceSchema = import_zod.z.object({
1282
1289
  allowedMethods: import_zod.z.array(ApiHttpMethodEnum).optional(),
1283
1290
  defaultHeaders: import_zod.z.record(import_zod.z.string(), import_zod.z.string()).optional(),
1284
1291
  maxBodyBytes: import_zod.z.number().int().positive().optional(),
1285
- endpoints: import_zod.z.array(ApiEndpointSchema).optional()
1286
- }).strict();
1292
+ endpoints: import_zod.z.array(ApiEndpointSchema).optional(),
1293
+ secretHeaders: import_zod.z.record(import_zod.z.string(), import_zod.z.string().min(1)).optional()
1294
+ }).strict().superRefine((svc, ctx) => {
1295
+ if (svc.secretHeaders === void 0) return;
1296
+ const lowerDefault = /* @__PURE__ */ new Set();
1297
+ for (const k of Object.keys(svc.defaultHeaders ?? {})) lowerDefault.add(k.toLowerCase());
1298
+ for (const headerName of Object.keys(svc.secretHeaders)) {
1299
+ if (!HEADER_NAME_RE.test(headerName)) {
1300
+ ctx.addIssue({
1301
+ code: "custom",
1302
+ message: `secretHeaders key "${headerName}" is not a valid HTTP header name (RFC 7230 token charset)`,
1303
+ path: ["secretHeaders", headerName]
1304
+ });
1305
+ continue;
1306
+ }
1307
+ const lower = headerName.toLowerCase();
1308
+ if (RESERVED_HEADER_NAMES.has(lower)) {
1309
+ ctx.addIssue({
1310
+ code: "custom",
1311
+ message: `secretHeaders key "${headerName}" is reserved \u2014 primary \`auth\` owns ${headerName}`,
1312
+ path: ["secretHeaders", headerName]
1313
+ });
1314
+ continue;
1315
+ }
1316
+ if (lowerDefault.has(lower)) {
1317
+ ctx.addIssue({
1318
+ code: "custom",
1319
+ message: `secretHeaders key "${headerName}" collides with defaultHeaders (case-insensitive). Move the secret-bearing version to secretHeaders only.`,
1320
+ path: ["secretHeaders", headerName]
1321
+ });
1322
+ }
1323
+ }
1324
+ });
1287
1325
  var ApiCatalogModeEnum = import_zod.z.enum(["eager", "lazy", "auto"]);
1288
1326
  var ApiConfigResolved = import_zod.z.object({
1289
1327
  services: import_zod.z.array(ApiServiceSchema),
@@ -8380,6 +8418,12 @@ function createApiCallTool(opts) {
8380
8418
  `createApiCallTool: service "${svc.name}" uses custom auth (id: ${svc.auth.id}) but no resolveAuth was supplied`
8381
8419
  );
8382
8420
  }
8421
+ const hasSecretHeaders = svc.secretHeaders !== void 0 && Object.keys(svc.secretHeaders).length > 0;
8422
+ if (hasSecretHeaders && opts.resolveAuth === void 0) {
8423
+ throw new Error(
8424
+ `createApiCallTool: service "${svc.name}" declares secretHeaders but no resolveAuth was supplied (the resolver is required to look up the secret values)`
8425
+ );
8426
+ }
8383
8427
  }
8384
8428
  const fetchFn = opts.fetch ?? globalThis.fetch.bind(globalThis);
8385
8429
  const maxResponseBytes = opts.maxResponseBytes ?? DEFAULT_MAX_RESPONSE_BYTES;
@@ -8444,13 +8488,20 @@ function createApiCallTool(opts) {
8444
8488
  return errResult(`ERR_API_BODY_TOO_LARGE: exceeds ${cap} bytes`);
8445
8489
  }
8446
8490
  }
8491
+ const secretHeaderRefs = svc.secretHeaders !== void 0 && Object.keys(svc.secretHeaders).length > 0 ? svc.secretHeaders : void 0;
8447
8492
  let authHeaders;
8448
8493
  try {
8449
8494
  authHeaders = await resolveAuth({
8450
8495
  auth: svc.auth ?? { type: "none" },
8451
8496
  env: opts.env,
8452
8497
  resolver: opts.resolveAuth,
8453
- ctx: { serviceName: svc.name, method: input.method, path: input.path }
8498
+ ctx: {
8499
+ serviceName: svc.name,
8500
+ method: input.method,
8501
+ path: input.path,
8502
+ ...secretHeaderRefs !== void 0 ? { secretHeaderRefs } : {}
8503
+ },
8504
+ forceResolve: secretHeaderRefs !== void 0
8454
8505
  });
8455
8506
  } catch (err) {
8456
8507
  const raw2 = err instanceof Error ? err.message : String(err);
@@ -8559,22 +8610,27 @@ function sanitizeHeaders(user, auth) {
8559
8610
  return out;
8560
8611
  }
8561
8612
  async function resolveAuth(args) {
8562
- const { auth, env, resolver, ctx } = args;
8613
+ const { auth, env, resolver, ctx, forceResolve } = args;
8614
+ let primary;
8563
8615
  switch (auth.type) {
8564
8616
  case "none":
8565
- return {};
8617
+ primary = {};
8618
+ break;
8566
8619
  case "bearer": {
8567
8620
  const token = envLookup(env, auth.tokenRef);
8568
- return { Authorization: `Bearer ${token}` };
8621
+ primary = { Authorization: `Bearer ${token}` };
8622
+ break;
8569
8623
  }
8570
8624
  case "header": {
8571
8625
  const value = envLookup(env, auth.valueRef);
8572
- return { [auth.name]: value };
8626
+ primary = { [auth.name]: value };
8627
+ break;
8573
8628
  }
8574
8629
  case "basic": {
8575
8630
  const u = envLookup(env, auth.userRef);
8576
8631
  const p = envLookup(env, auth.passRef);
8577
- return { Authorization: `Basic ${base64(`${u}:${p}`)}` };
8632
+ primary = { Authorization: `Basic ${base64(`${u}:${p}`)}` };
8633
+ break;
8578
8634
  }
8579
8635
  case "custom":
8580
8636
  if (resolver === void 0) {
@@ -8582,6 +8638,14 @@ async function resolveAuth(args) {
8582
8638
  }
8583
8639
  return resolver(auth, ctx);
8584
8640
  }
8641
+ if (forceResolve === true) {
8642
+ if (resolver === void 0) {
8643
+ throw new Error("secretHeaders require a resolveAuth callback (host did not supply one)");
8644
+ }
8645
+ const extra = await resolver(auth, ctx);
8646
+ return { ...primary, ...extra };
8647
+ }
8648
+ return primary;
8585
8649
  }
8586
8650
  function envLookup(env, ref) {
8587
8651
  if (env === void 0 || env[ref] === void 0) {