la-machina-engine 0.8.0 → 0.9.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/README.md CHANGED
@@ -1301,6 +1301,28 @@ model cannot spoof `Authorization` via `input.headers`).
1301
1301
  dispatch with `{ service, method, path, status, latencyMs, bytesIn }`
1302
1302
  — no secrets — for metering, billing, audit logs.
1303
1303
 
1304
+ **Raw-body uploads (0.9.0):** set `bodyEncoding: 'raw'` on the call to
1305
+ send a string body verbatim — no `JSON.stringify`. Use for upload APIs
1306
+ that take binary or text-blob bodies (Drive media upload, S3
1307
+ PutObject, image push, log ingestion, etc.). The caller-supplied
1308
+ `Content-Type` header wins; default falls back to `text/plain`.
1309
+
1310
+ ```ts
1311
+ ApiCall({
1312
+ service: 'gdrive',
1313
+ method: 'PATCH',
1314
+ path: `/upload/drive/v3/files/${fileId}?uploadType=media`,
1315
+ headers: { 'Content-Type': 'text/markdown' },
1316
+ body: '# Hello world',
1317
+ bodyEncoding: 'raw',
1318
+ })
1319
+ ```
1320
+
1321
+ `bodyEncoding: 'raw'` requires the body to be a string — passing an
1322
+ object returns `ERR_API_RAW_BODY_NOT_STRING` and never makes the
1323
+ fetch. The default `'json'` encoding behaves exactly as in 0.8.x.
1324
+ `maxBodyBytes` is enforced under both encodings.
1325
+
1304
1326
  **Disabling:** `tools.disabled: ['ApiCall']` turns it off even when
1305
1327
  services are configured. Absent `config.api` → tool never registered,
1306
1328
  no prompt mention.
package/dist/index.cjs CHANGED
@@ -8208,6 +8208,19 @@ function createApiCallTool(opts) {
8208
8208
  path: import_zod23.z.string().regex(/^\//, "path must start with /"),
8209
8209
  query: import_zod23.z.record(import_zod23.z.string(), import_zod23.z.string()).optional(),
8210
8210
  body: import_zod23.z.unknown().optional(),
8211
+ /**
8212
+ * Plan 032 — how to encode the body before sending.
8213
+ *
8214
+ * 'json' (default, back-compat): `JSON.stringify(body)` and
8215
+ * Content-Type defaults to `application/json` (caller
8216
+ * header still wins).
8217
+ * 'raw': `body` MUST be a string, sent verbatim. Caller-
8218
+ * supplied Content-Type wins; default falls back to
8219
+ * `text/plain`. Use for binary or text-blob upload
8220
+ * APIs (Drive media upload, S3 PutObject, log
8221
+ * ingestion, image push, etc.).
8222
+ */
8223
+ bodyEncoding: import_zod23.z.enum(["json", "raw"]).optional(),
8211
8224
  headers: import_zod23.z.record(import_zod23.z.string(), import_zod23.z.string()).optional()
8212
8225
  });
8213
8226
  const description = opts.toolDescription ?? `Call a configured external API. Services: ${serviceNames.join(", ")}. Auth is injected automatically \u2014 do not pass credentials via headers.`;
@@ -8230,8 +8243,20 @@ function createApiCallTool(opts) {
8230
8243
  return errResult(`ERR_API_PATH_NOT_ALLOWED: ${input.path} for service ${svc.name}`);
8231
8244
  }
8232
8245
  let bodyText;
8246
+ let defaultContentType;
8233
8247
  if (input.body !== void 0) {
8234
- bodyText = JSON.stringify(input.body);
8248
+ if (input.bodyEncoding === "raw") {
8249
+ if (typeof input.body !== "string") {
8250
+ return errResult(
8251
+ "ERR_API_RAW_BODY_NOT_STRING: bodyEncoding=raw requires body to be a string"
8252
+ );
8253
+ }
8254
+ bodyText = input.body;
8255
+ defaultContentType = "text/plain";
8256
+ } else {
8257
+ bodyText = JSON.stringify(input.body);
8258
+ defaultContentType = "application/json";
8259
+ }
8235
8260
  const cap = svc.maxBodyBytes ?? DEFAULT_MAX_BODY_BYTES;
8236
8261
  if (byteLength2(bodyText) > cap) {
8237
8262
  return errResult(`ERR_API_BODY_TOO_LARGE: exceeds ${cap} bytes`);
@@ -8263,7 +8288,10 @@ function createApiCallTool(opts) {
8263
8288
  res = await fetchFn(url, {
8264
8289
  method: input.method,
8265
8290
  headers: {
8266
- "Content-Type": "application/json",
8291
+ // Plan 032 — Content-Type default depends on body encoding;
8292
+ // omit when there's no body. Caller-supplied Content-Type
8293
+ // (in `userHeaders`) wins through normal merge order.
8294
+ ...defaultContentType !== void 0 ? { "Content-Type": defaultContentType } : {},
8267
8295
  ...svc.defaultHeaders ?? {},
8268
8296
  ...userHeaders,
8269
8297
  ...authHeaders