la-machina-engine 0.8.0 → 0.10.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
@@ -7979,7 +7979,10 @@ function getMcpSection(options) {
7979
7979
  // src/prompts/systemPrompt.ts
7980
7980
  async function buildSystemPrompt(options) {
7981
7981
  const sections = [];
7982
- if (!options.coordinatorMode) {
7982
+ if (options.coordinatorMode) {
7983
+ } else if (options.staticBase !== void 0 && options.staticBase.length > 0) {
7984
+ sections.push(options.staticBase);
7985
+ } else {
7983
7986
  sections.push(getBaseSection());
7984
7987
  sections.push(getDoingTasksSection());
7985
7988
  sections.push(getActionsSection());
@@ -8208,6 +8211,19 @@ function createApiCallTool(opts) {
8208
8211
  path: import_zod23.z.string().regex(/^\//, "path must start with /"),
8209
8212
  query: import_zod23.z.record(import_zod23.z.string(), import_zod23.z.string()).optional(),
8210
8213
  body: import_zod23.z.unknown().optional(),
8214
+ /**
8215
+ * Plan 032 — how to encode the body before sending.
8216
+ *
8217
+ * 'json' (default, back-compat): `JSON.stringify(body)` and
8218
+ * Content-Type defaults to `application/json` (caller
8219
+ * header still wins).
8220
+ * 'raw': `body` MUST be a string, sent verbatim. Caller-
8221
+ * supplied Content-Type wins; default falls back to
8222
+ * `text/plain`. Use for binary or text-blob upload
8223
+ * APIs (Drive media upload, S3 PutObject, log
8224
+ * ingestion, image push, etc.).
8225
+ */
8226
+ bodyEncoding: import_zod23.z.enum(["json", "raw"]).optional(),
8211
8227
  headers: import_zod23.z.record(import_zod23.z.string(), import_zod23.z.string()).optional()
8212
8228
  });
8213
8229
  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 +8246,20 @@ function createApiCallTool(opts) {
8230
8246
  return errResult(`ERR_API_PATH_NOT_ALLOWED: ${input.path} for service ${svc.name}`);
8231
8247
  }
8232
8248
  let bodyText;
8249
+ let defaultContentType;
8233
8250
  if (input.body !== void 0) {
8234
- bodyText = JSON.stringify(input.body);
8251
+ if (input.bodyEncoding === "raw") {
8252
+ if (typeof input.body !== "string") {
8253
+ return errResult(
8254
+ "ERR_API_RAW_BODY_NOT_STRING: bodyEncoding=raw requires body to be a string"
8255
+ );
8256
+ }
8257
+ bodyText = input.body;
8258
+ defaultContentType = "text/plain";
8259
+ } else {
8260
+ bodyText = JSON.stringify(input.body);
8261
+ defaultContentType = "application/json";
8262
+ }
8235
8263
  const cap = svc.maxBodyBytes ?? DEFAULT_MAX_BODY_BYTES;
8236
8264
  if (byteLength2(bodyText) > cap) {
8237
8265
  return errResult(`ERR_API_BODY_TOO_LARGE: exceeds ${cap} bytes`);
@@ -8263,7 +8291,10 @@ function createApiCallTool(opts) {
8263
8291
  res = await fetchFn(url, {
8264
8292
  method: input.method,
8265
8293
  headers: {
8266
- "Content-Type": "application/json",
8294
+ // Plan 032 — Content-Type default depends on body encoding;
8295
+ // omit when there's no body. Caller-supplied Content-Type
8296
+ // (in `userHeaders`) wins through normal merge order.
8297
+ ...defaultContentType !== void 0 ? { "Content-Type": defaultContentType } : {},
8267
8298
  ...svc.defaultHeaders ?? {},
8268
8299
  ...userHeaders,
8269
8300
  ...authHeaders
@@ -10494,6 +10525,7 @@ var Engine = class {
10494
10525
  const knowledgeRuntime = this.resolveKnowledgeRuntime(options.knowledge, storage);
10495
10526
  let systemPrompt = await buildSystemPrompt({
10496
10527
  ...coordinatorBase !== void 0 ? { base: coordinatorBase } : {},
10528
+ ...options.systemPromptBase !== void 0 ? { staticBase: options.systemPromptBase } : {},
10497
10529
  memory,
10498
10530
  storage,
10499
10531
  // When an override was supplied, skip the legacy disk-scan path.
@@ -10691,6 +10723,7 @@ var Engine = class {
10691
10723
  const knowledgeRuntime = this.resolveKnowledgeRuntime(options.knowledge, storage);
10692
10724
  let systemPrompt = await buildSystemPrompt({
10693
10725
  ...coordinatorBase !== void 0 ? { base: coordinatorBase } : {},
10726
+ ...options.systemPromptBase !== void 0 ? { staticBase: options.systemPromptBase } : {},
10694
10727
  memory,
10695
10728
  storage,
10696
10729
  // When an override was supplied, skip the legacy disk-scan path.