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 +22 -0
- package/dist/index.cjs +30 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +30 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
-
|
|
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
|
-
|
|
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
|