@mindstudio-ai/agent 0.1.58 → 0.1.60

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.js CHANGED
@@ -275,7 +275,7 @@ function serializeParam(val) {
275
275
  function serializeColumnParam(val, columnName, columns) {
276
276
  const col = columns.find((c) => c.name === columnName);
277
277
  if (col?.type === "user" && typeof val === "string") {
278
- return `@@user@@${val}`;
278
+ return val.startsWith(USER_PREFIX) ? val : `${USER_PREFIX}${val}`;
279
279
  }
280
280
  return serializeParam(val);
281
281
  }
@@ -293,7 +293,7 @@ function deserializeRow(row, columns) {
293
293
  const result = {};
294
294
  for (const [key, value] of Object.entries(row)) {
295
295
  const col = columns.find((c) => c.name === key);
296
- if (col?.type === "user" && typeof value === "string" && value.startsWith(USER_PREFIX)) {
296
+ if (typeof value === "string" && value.startsWith(USER_PREFIX)) {
297
297
  result[key] = value.slice(USER_PREFIX.length);
298
298
  } else if (col?.type === "json" && typeof value === "string") {
299
299
  try {
@@ -396,16 +396,16 @@ function stripSystemColumns(data) {
396
396
  }
397
397
 
398
398
  // src/db/predicate.ts
399
- function compilePredicate(fn) {
399
+ function compilePredicate(fn, bindings) {
400
400
  try {
401
401
  const source = fn.toString();
402
- const paramName = extractParamName(source);
403
- if (!paramName) return { type: "js", fn, reason: "could not extract parameter name" };
402
+ const names = extractParamNames(source);
403
+ if (!names) return { type: "js", fn, reason: "could not extract parameter name" };
404
404
  const body = extractBody(source);
405
405
  if (!body) return { type: "js", fn, reason: "could not extract function body" };
406
406
  const tokens = tokenize(body);
407
407
  if (tokens.length === 0) return { type: "js", fn, reason: "empty token stream" };
408
- const parser = new Parser(tokens, paramName, fn);
408
+ const parser = new Parser(tokens, names.row, names.bindings, bindings, fn);
409
409
  const ast = parser.parseExpression();
410
410
  if (!ast) return { type: "js", fn, reason: "could not parse expression" };
411
411
  if (parser.pos < tokens.length) return { type: "js", fn, reason: "unexpected tokens after expression" };
@@ -416,11 +416,44 @@ function compilePredicate(fn) {
416
416
  return { type: "js", fn, reason: `compilation error: ${err?.message || "unknown"}` };
417
417
  }
418
418
  }
419
- function extractParamName(source) {
420
- const match = source.match(
421
- /^\s*(?:\(?\s*([a-zA-Z_$][a-zA-Z0-9_$]*)\s*(?::[^)]*?)?\)?\s*=>)/
422
- );
423
- return match?.[1] ?? null;
419
+ function extractParamNames(source) {
420
+ const arrowIdx = source.indexOf("=>");
421
+ if (arrowIdx === -1) return null;
422
+ let paramList = source.slice(0, arrowIdx).trim();
423
+ if (paramList.startsWith("(") && paramList.endsWith(")")) {
424
+ paramList = paramList.slice(1, -1).trim();
425
+ }
426
+ if (paramList.length === 0) return null;
427
+ const parts = splitParams(paramList);
428
+ if (parts.length === 0 || parts.length > 2) return null;
429
+ const row = stripTypeAnnotation(parts[0]);
430
+ if (!row) return null;
431
+ if (parts.length === 1) return { row };
432
+ const bindings = stripTypeAnnotation(parts[1]);
433
+ if (!bindings) return null;
434
+ return { row, bindings };
435
+ }
436
+ function splitParams(input) {
437
+ const parts = [];
438
+ let depth = 0;
439
+ let current = "";
440
+ for (const ch of input) {
441
+ if (ch === "<" || ch === "(") depth++;
442
+ else if (ch === ">" || ch === ")") depth--;
443
+ if (ch === "," && depth === 0) {
444
+ parts.push(current.trim());
445
+ current = "";
446
+ } else {
447
+ current += ch;
448
+ }
449
+ }
450
+ if (current.trim()) parts.push(current.trim());
451
+ return parts;
452
+ }
453
+ function stripTypeAnnotation(part) {
454
+ const colonIdx = part.indexOf(":");
455
+ const name = (colonIdx === -1 ? part : part.slice(0, colonIdx)).trim();
456
+ return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name) ? name : null;
424
457
  }
425
458
  function extractBody(source) {
426
459
  const arrowIdx = source.indexOf("=>");
@@ -531,9 +564,11 @@ function tokenize(expr) {
531
564
  return tokens;
532
565
  }
533
566
  var Parser = class {
534
- constructor(tokens, paramName, originalFn) {
567
+ constructor(tokens, paramName, bindingsName, bindingsValue, originalFn) {
535
568
  this.tokens = tokens;
536
569
  this.paramName = paramName;
570
+ this.bindingsName = bindingsName;
571
+ this.bindingsValue = bindingsValue;
537
572
  this.originalFn = originalFn;
538
573
  }
539
574
  pos = 0;
@@ -630,6 +665,9 @@ var Parser = class {
630
665
  if (this.match("identifier", this.paramName)) {
631
666
  return this.parseFieldExpression();
632
667
  }
668
+ if (this.bindingsName && this.match("identifier", this.bindingsName)) {
669
+ return this.parseBindingsArrayIncludes();
670
+ }
633
671
  if (this.match("identifier")) {
634
672
  return this.parseNonParamExpression();
635
673
  }
@@ -666,6 +704,7 @@ var Parser = class {
666
704
  if (!this.match("identifier")) return null;
667
705
  const parts = [this.advance().value];
668
706
  while (this.match("dot") && this.tokens[this.pos + 1]?.type === "identifier") {
707
+ if (this.tokens[this.pos + 2]?.type === "lparen") break;
669
708
  this.advance();
670
709
  parts.push(this.advance().value);
671
710
  }
@@ -750,6 +789,68 @@ var Parser = class {
750
789
  if (ident === "true" || ident === "false") return null;
751
790
  return null;
752
791
  }
792
+ /**
793
+ * Parse `$.ids.includes(o.field)` → IN expression with resolved values.
794
+ * The bindings identifier has been peeked but not consumed.
795
+ *
796
+ * Falls back (returns null) if the resolved bindings value isn't an array,
797
+ * or if the path doesn't exist on the bindings object.
798
+ */
799
+ parseBindingsArrayIncludes() {
800
+ const bound = this.tryResolveBindingsValue();
801
+ if (bound === PARSE_FAILED) return null;
802
+ if (!Array.isArray(bound)) return null;
803
+ if (!this.eat("dot")) return null;
804
+ if (!this.match("identifier", "includes")) return null;
805
+ this.advance();
806
+ if (!this.eat("lparen")) return null;
807
+ if (!this.match("identifier", this.paramName)) return null;
808
+ this.advance();
809
+ const field = this.parseFieldPath();
810
+ if (!field) return null;
811
+ if (!this.eat("rparen")) return null;
812
+ return { kind: "in", field, values: bound };
813
+ }
814
+ /**
815
+ * If the current token is the bindings parameter name, walk a dotted path
816
+ * (`$.foo.bar`) and resolve the value from the bindings object. Returns
817
+ * the resolved value or `PARSE_FAILED`.
818
+ *
819
+ * Stops walking before a method call (e.g. doesn't consume `.includes` in
820
+ * `$.ids.includes(...)`) so the caller can dispatch on what follows.
821
+ *
822
+ * Restores `pos` on failure so callers can fall through cleanly.
823
+ */
824
+ tryResolveBindingsValue() {
825
+ if (!this.bindingsName) return PARSE_FAILED;
826
+ if (!this.match("identifier", this.bindingsName)) return PARSE_FAILED;
827
+ if (this.bindingsValue == null) return PARSE_FAILED;
828
+ const startPos = this.pos;
829
+ this.advance();
830
+ const path = [];
831
+ while (this.match("dot") && this.tokens[this.pos + 1]?.type === "identifier") {
832
+ if (this.tokens[this.pos + 2]?.type === "lparen") break;
833
+ this.advance();
834
+ path.push(this.advance().value);
835
+ }
836
+ if (path.length === 0) {
837
+ this.pos = startPos;
838
+ return PARSE_FAILED;
839
+ }
840
+ let value = this.bindingsValue;
841
+ for (const key of path) {
842
+ if (value == null || typeof value !== "object") {
843
+ this.pos = startPos;
844
+ return PARSE_FAILED;
845
+ }
846
+ value = value[key];
847
+ }
848
+ if (value === void 0) {
849
+ this.pos = startPos;
850
+ return PARSE_FAILED;
851
+ }
852
+ return value;
853
+ }
753
854
  /**
754
855
  * Parse a literal value or closure variable reference.
755
856
  *
@@ -784,6 +885,10 @@ var Parser = class {
784
885
  this.advance();
785
886
  return void 0;
786
887
  }
888
+ if (this.bindingsName && t.value === this.bindingsName) {
889
+ const bound = this.tryResolveBindingsValue();
890
+ if (bound !== PARSE_FAILED) return bound;
891
+ }
787
892
  return this.resolveClosureVariable();
788
893
  }
789
894
  if (t.type === "operator" && t.value === "-") {
@@ -918,11 +1023,10 @@ var Query = class _Query {
918
1023
  rawWhereParams: this._rawWhereParams
919
1024
  });
920
1025
  }
921
- // -------------------------------------------------------------------------
922
- // Chain methods
923
- // -------------------------------------------------------------------------
924
- filter(predicate) {
925
- return this._clone({ predicates: [...this._predicates, predicate] });
1026
+ filter(predicate, bindings) {
1027
+ return this._clone({
1028
+ predicates: [...this._predicates, { fn: predicate, bindings }]
1029
+ });
926
1030
  }
927
1031
  sortBy(accessor) {
928
1032
  return this._clone({ sortAccessor: accessor });
@@ -979,7 +1083,7 @@ var Query = class _Query {
979
1083
  if (this._predicates.length === 0) return true;
980
1084
  const allRows = await this._fetchAllRows();
981
1085
  return allRows.every(
982
- (row) => this._predicates.every((pred) => pred(row))
1086
+ (row) => this._predicates.every((p) => p.fn(row, p.bindings))
983
1087
  );
984
1088
  }
985
1089
  min(accessor) {
@@ -1067,7 +1171,7 @@ var Query = class _Query {
1067
1171
  if (compiled.query) {
1068
1172
  return compiled.postProcess ? compiled.postProcess(rows) : rows;
1069
1173
  }
1070
- let filtered = compiled.predicates ? rows.filter((row) => compiled.predicates.every((pred) => pred(row))) : rows;
1174
+ let filtered = compiled.predicates ? rows.filter((row) => compiled.predicates.every((p) => p.fn(row, p.bindings))) : rows;
1071
1175
  if (compiled.sortAccessor) {
1072
1176
  const accessor = compiled.sortAccessor;
1073
1177
  const reversed = compiled.reversed ?? false;
@@ -1157,7 +1261,7 @@ var Query = class _Query {
1157
1261
  if (this._predicates.length === 0) {
1158
1262
  return { allSql: true, sqlWhere: "", compiled: [] };
1159
1263
  }
1160
- const compiled = this._predicates.map((pred) => compilePredicate(pred));
1264
+ const compiled = this._predicates.map((p) => compilePredicate(p.fn, p.bindings));
1161
1265
  const allSql = compiled.every((c) => c.type === "sql");
1162
1266
  let sqlWhere = "";
1163
1267
  if (allSql) {
@@ -1176,7 +1280,7 @@ var Query = class _Query {
1176
1280
  );
1177
1281
  }
1178
1282
  return allRows.filter(
1179
- (row) => this._predicates.every((pred) => pred(row))
1283
+ (row) => this._predicates.every((p) => p.fn(row, p.bindings))
1180
1284
  );
1181
1285
  }
1182
1286
  async _fetchAllRows() {
@@ -1296,21 +1400,18 @@ var Table = class {
1296
1400
  postProcess: (rows) => rows[0] ?? null
1297
1401
  });
1298
1402
  }
1299
- /** Find the first row matching a predicate. Returns null if none match. */
1300
- findOne(predicate) {
1301
- return this.filter(predicate).first();
1403
+ findOne(predicate, bindings) {
1404
+ return this.filter(predicate, bindings).first();
1302
1405
  }
1303
- count(predicate) {
1304
- if (predicate) return this.filter(predicate).count();
1406
+ count(predicate, bindings) {
1407
+ if (predicate) return this.filter(predicate, bindings).count();
1305
1408
  return this.toArray().count();
1306
1409
  }
1307
- /** True if any row matches the predicate. */
1308
- some(predicate) {
1309
- return this.filter(predicate).some();
1410
+ some(predicate, bindings) {
1411
+ return this.filter(predicate, bindings).some();
1310
1412
  }
1311
- /** True if all rows match the predicate. */
1312
- async every(predicate) {
1313
- return this.filter(predicate).every();
1413
+ async every(predicate, bindings) {
1414
+ return this.filter(predicate, bindings).every();
1314
1415
  }
1315
1416
  /** True if the table has zero rows. */
1316
1417
  async isEmpty() {
@@ -1335,9 +1436,8 @@ var Table = class {
1335
1436
  toArray() {
1336
1437
  return new Query(this._config);
1337
1438
  }
1338
- /** Filter rows by a predicate. Returns a chainable Query. */
1339
- filter(predicate) {
1340
- return new Query(this._config).filter(predicate);
1439
+ filter(predicate, bindings) {
1440
+ return new Query(this._config).filter(predicate, bindings);
1341
1441
  }
1342
1442
  /** Sort rows by a field. Returns a chainable Query. */
1343
1443
  sortBy(accessor) {
@@ -1419,11 +1519,8 @@ var Table = class {
1419
1519
  deleted: results[0].changes > 0
1420
1520
  }));
1421
1521
  }
1422
- /**
1423
- * Remove all rows matching a predicate. Returns the count removed.
1424
- */
1425
- removeAll(predicate) {
1426
- const compiled = compilePredicate(predicate);
1522
+ removeAll(predicate, bindings) {
1523
+ const compiled = compilePredicate(predicate, bindings);
1427
1524
  if (compiled.type === "sql") {
1428
1525
  const query = buildDelete(this._config.tableName, compiled.where);
1429
1526
  return new Mutation(this._config, [query], (results) => results[0].changes);
@@ -1440,7 +1537,7 @@ var Table = class {
1440
1537
  this._config.columns
1441
1538
  )
1442
1539
  );
1443
- const matching = allRows.filter((row) => predicate(row));
1540
+ const matching = allRows.filter((row) => predicate(row, bindings));
1444
1541
  if (matching.length === 0) return 0;
1445
1542
  const deleteQueries = matching.filter((row) => row.id).map((row) => buildDelete(this._config.tableName, `id = ?`, [row.id]));
1446
1543
  if (deleteQueries.length > 0) {
@@ -1592,6 +1689,8 @@ function createDb(databases, executeBatch, authConfig, syncRoles) {
1592
1689
  minutes: (n) => n * 6e4,
1593
1690
  ago: (ms) => Date.now() - ms,
1594
1691
  fromNow: (ms) => Date.now() + ms,
1692
+ // --- User references ---
1693
+ userRef: (id) => id.startsWith(USER_PREFIX) ? id.slice(USER_PREFIX.length) : id,
1595
1694
  // --- Batch execution ---
1596
1695
  batch: ((...operations) => {
1597
1696
  return (async () => {
@@ -2160,13 +2259,6 @@ var stepMetadata = {
2160
2259
  inputSchema: { "type": "object", "properties": { "mediaUrl": { "type": "string", "description": "URL of the audio or video file to analyze" } }, "required": ["mediaUrl"] },
2161
2260
  outputSchema: { "type": "object", "properties": { "metadata": { "type": "string", "description": "JSON string containing the media file metadata" } }, "required": ["metadata"] }
2162
2261
  },
2163
- "httpRequest": {
2164
- stepType: "httpRequest",
2165
- description: "Make an HTTP request to an external endpoint and return the response.",
2166
- usageNotes: "- Supports GET, POST, PATCH, DELETE, and PUT methods.\n- Body can be raw JSON/text, URL-encoded form data, or multipart form data.",
2167
- inputSchema: { "type": "object", "properties": { "url": { "type": "string", "description": "The request URL" }, "method": { "type": "string", "description": "HTTP method (GET, POST, PATCH, DELETE, or PUT)" }, "headers": { "type": "object", "properties": {}, "required": [], "description": "Custom request headers as key-value pairs" }, "queryParams": { "type": "object", "properties": {}, "required": [], "description": "Query string parameters as key-value pairs" }, "body": { "type": "string", "description": "Raw request body (used for JSON or custom content types)" }, "bodyItems": { "type": "object", "properties": {}, "required": [], "description": "Key-value body items (used for form data or URL-encoded content types)" }, "contentType": { "enum": ["none", "application/json", "application/x-www-form-urlencoded", "multipart/form-data", "custom"], "type": "string", "description": "The content type for the request body" }, "customContentType": { "type": "string", "description": 'Custom Content-Type header value (used when contentType is "custom")' }, "testData": { "type": "object", "properties": {}, "required": [], "description": "Test data for debug/preview mode" } }, "required": ["url", "method", "headers", "queryParams", "body", "bodyItems", "contentType", "customContentType"], "description": "HTTP request configuration" },
2168
- outputSchema: { "type": "object", "properties": { "ok": { "type": "boolean", "description": "Whether the HTTP response status code is in the 2xx range" }, "status": { "type": "number", "description": "HTTP response status code" }, "statusText": { "type": "string", "description": "HTTP response status text" }, "response": { "type": "string", "description": "Response body as a string" } }, "required": ["ok", "status", "statusText", "response"] }
2169
- },
2170
2262
  "hubspotCreateCompany": {
2171
2263
  stepType: "hubspotCreateCompany",
2172
2264
  description: "Create a new company or update an existing one in HubSpot. Matches by domain.",
@@ -3272,9 +3364,6 @@ function applyStepMethods(AgentClass) {
3272
3364
  proto.getMediaMetadata = function(step, options) {
3273
3365
  return this.executeStep("getMediaMetadata", step, options);
3274
3366
  };
3275
- proto.httpRequest = function(step, options) {
3276
- return this.executeStep("httpRequest", step, options);
3277
- };
3278
3367
  proto.hubspotCreateCompany = function(step, options) {
3279
3368
  return this.executeStep("hubspotCreateCompany", step, options);
3280
3369
  };
@@ -3626,7 +3715,11 @@ var MindStudioAgent = class {
3626
3715
  get _currentHttpConfig() {
3627
3716
  const rctx = getRequestContext();
3628
3717
  if (rctx?.remoteHostname) {
3629
- return { ...this._httpConfig, baseUrl: rctx.remoteHostname, token: this._token };
3718
+ return {
3719
+ ...this._httpConfig,
3720
+ baseUrl: rctx.remoteHostname,
3721
+ token: this._token
3722
+ };
3630
3723
  }
3631
3724
  return this._httpConfig;
3632
3725
  }
@@ -3642,7 +3735,11 @@ var MindStudioAgent = class {
3642
3735
  _getContext() {
3643
3736
  const rctx = getRequestContext();
3644
3737
  if (rctx?.auth && rctx?.databases) {
3645
- return { auth: rctx.auth, databases: rctx.databases, authConfig: rctx.authConfig };
3738
+ return {
3739
+ auth: rctx.auth,
3740
+ databases: rctx.databases,
3741
+ authConfig: rctx.authConfig
3742
+ };
3646
3743
  }
3647
3744
  return this._context;
3648
3745
  }
@@ -3705,7 +3802,8 @@ var MindStudioAgent = class {
3705
3802
  const res = await fetch(pollUrl, {
3706
3803
  headers: { "User-Agent": "@mindstudio-ai/agent" }
3707
3804
  });
3708
- if (res.status === 502 || res.status === 503 || res.status === 504) continue;
3805
+ if (res.status === 502 || res.status === 503 || res.status === 504)
3806
+ continue;
3709
3807
  if (res.status === 404) {
3710
3808
  throw new MindStudioError(
3711
3809
  `[${stepType}] Execution token expired.`,
@@ -3802,7 +3900,9 @@ var MindStudioAgent = class {
3802
3900
  const errMsg = (typeof body2.error === "string" ? body2.error : void 0) ?? (typeof body2.message === "string" ? body2.message : void 0) ?? (typeof body2.details === "string" ? body2.details : void 0);
3803
3901
  if (errMsg) message = errMsg;
3804
3902
  else if (body2.error || body2.message || body2.details) {
3805
- message = JSON.stringify(body2.error ?? body2.message ?? body2.details);
3903
+ message = JSON.stringify(
3904
+ body2.error ?? body2.message ?? body2.details
3905
+ );
3806
3906
  }
3807
3907
  if (body2.code) code = body2.code;
3808
3908
  } catch {
@@ -3811,7 +3911,12 @@ var MindStudioAgent = class {
3811
3911
  }
3812
3912
  } catch {
3813
3913
  }
3814
- throw new MindStudioError(`[${stepType}] ${message}`, code, res.status, details);
3914
+ throw new MindStudioError(
3915
+ `[${stepType}] ${message}`,
3916
+ code,
3917
+ res.status,
3918
+ details
3919
+ );
3815
3920
  }
3816
3921
  const headers = res.headers;
3817
3922
  try {
@@ -3943,7 +4048,10 @@ var MindStudioAgent = class {
3943
4048
  async executeStepBatch(steps, options) {
3944
4049
  const threadId = options?.threadId ?? (this._reuseThreadId && !getRequestContext() ? this._threadId : void 0);
3945
4050
  const { data: asyncData } = await request(this._currentHttpConfig, "POST", "/steps/execute-batch-async", {
3946
- steps: steps.map((s) => ({ ...s, stepType: resolveStepType2(s.stepType) })),
4051
+ steps: steps.map((s) => ({
4052
+ ...s,
4053
+ stepType: resolveStepType2(s.stepType)
4054
+ })),
3947
4055
  ...options?.appId != null && { appId: options.appId },
3948
4056
  ...threadId != null && { threadId }
3949
4057
  });
@@ -3955,7 +4063,8 @@ var MindStudioAgent = class {
3955
4063
  const res = await fetch(pollUrl, {
3956
4064
  headers: { "User-Agent": "@mindstudio-ai/agent" }
3957
4065
  });
3958
- if (res.status === 502 || res.status === 503 || res.status === 504) continue;
4066
+ if (res.status === 502 || res.status === 503 || res.status === 504)
4067
+ continue;
3959
4068
  if (res.status === 404) {
3960
4069
  throw new MindStudioError(
3961
4070
  "Batch poll token not found or expired.",
@@ -4119,7 +4228,8 @@ var MindStudioAgent = class {
4119
4228
  const res = await fetch(pollUrl, {
4120
4229
  headers: { "User-Agent": "@mindstudio-ai/agent" }
4121
4230
  });
4122
- if (res.status === 502 || res.status === 503 || res.status === 504) continue;
4231
+ if (res.status === 502 || res.status === 503 || res.status === 504)
4232
+ continue;
4123
4233
  if (res.status === 404) {
4124
4234
  throw new MindStudioError(
4125
4235
  "Poll token not found or expired.",
@@ -4235,6 +4345,15 @@ var MindStudioAgent = class {
4235
4345
  );
4236
4346
  return data;
4237
4347
  }
4348
+ /** List packaged workflows available to the organization. */
4349
+ async listPackagedWorkflows() {
4350
+ const { data } = await request(
4351
+ this._currentHttpConfig,
4352
+ "GET",
4353
+ "/helpers/packaged-workflows"
4354
+ );
4355
+ return data;
4356
+ }
4238
4357
  // -------------------------------------------------------------------------
4239
4358
  // Helper methods — cost estimation
4240
4359
  // -------------------------------------------------------------------------
@@ -4465,7 +4584,9 @@ var MindStudioAgent = class {
4465
4584
  const errMsg = (typeof body.error === "string" ? body.error : void 0) ?? (typeof body.message === "string" ? body.message : void 0) ?? (typeof body.details === "string" ? body.details : void 0);
4466
4585
  if (errMsg) message = errMsg;
4467
4586
  else if (body.error || body.message || body.details) {
4468
- message = JSON.stringify(body.error ?? body.message ?? body.details);
4587
+ message = JSON.stringify(
4588
+ body.error ?? body.message ?? body.details
4589
+ );
4469
4590
  }
4470
4591
  if (body.code) code = body.code;
4471
4592
  } catch {
@@ -4473,11 +4594,7 @@ var MindStudioAgent = class {
4473
4594
  }
4474
4595
  } catch {
4475
4596
  }
4476
- throw new MindStudioError(
4477
- `[db] ${message}`,
4478
- code,
4479
- res.status
4480
- );
4597
+ throw new MindStudioError(`[db] ${message}`, code, res.status);
4481
4598
  }
4482
4599
  const data = await res.json();
4483
4600
  return data.results;
@@ -4572,6 +4689,7 @@ var MindStudioAgent = class {
4572
4689
  minutes: (n) => n * 6e4,
4573
4690
  ago: (ms) => Date.now() - ms,
4574
4691
  fromNow: (ms) => Date.now() + ms,
4692
+ userRef: (id) => id.startsWith("@@user@@") ? id.slice("@@user@@".length) : id,
4575
4693
  // Batch needs context — hydrate first, then delegate to real db
4576
4694
  batch: ((...queries) => {
4577
4695
  return (async () => {
@@ -4686,9 +4804,14 @@ var MindStudioAgent = class {
4686
4804
  }
4687
4805
  /** Update the profile picture of the authenticated user/agent. */
4688
4806
  async changeProfilePicture(url) {
4689
- await request(this._currentHttpConfig, "POST", "/account/change-profile-picture", {
4690
- url
4691
- });
4807
+ await request(
4808
+ this._currentHttpConfig,
4809
+ "POST",
4810
+ "/account/change-profile-picture",
4811
+ {
4812
+ url
4813
+ }
4814
+ );
4692
4815
  }
4693
4816
  /**
4694
4817
  * Upload a file to the MindStudio CDN.
@@ -4744,8 +4867,7 @@ function resolveToken(provided, config) {
4744
4867
  if (provided) return { token: provided, authType: "apiKey" };
4745
4868
  if (process.env.MINDSTUDIO_API_KEY)
4746
4869
  return { token: process.env.MINDSTUDIO_API_KEY, authType: "apiKey" };
4747
- if (config?.apiKey)
4748
- return { token: config.apiKey, authType: "apiKey" };
4870
+ if (config?.apiKey) return { token: config.apiKey, authType: "apiKey" };
4749
4871
  throw new MindStudioError(
4750
4872
  "No API key provided. Run `mindstudio login`, pass `apiKey` to the constructor, or set the MINDSTUDIO_API_KEY environment variable.",
4751
4873
  "missing_api_key",
@@ -4818,7 +4940,6 @@ var monacoSnippets = {
4818
4940
  "getGoogleDriveFile": { fields: [["fileId", "string"]], outputKeys: ["url", "name", "mimeType", "size"] },
4819
4941
  "getGoogleSheetInfo": { fields: [["documentId", "string"]], outputKeys: ["title", "sheets"] },
4820
4942
  "getMediaMetadata": { fields: [["mediaUrl", "string"]], outputKeys: ["metadata"] },
4821
- "httpRequest": { fields: [["url", "string"], ["method", "string"], ["headers", "object"], ["queryParams", "object"], ["body", "string"], ["bodyItems", "object"], ["contentType", ["none", "application/json", "application/x-www-form-urlencoded", "multipart/form-data", "custom"]], ["customContentType", "string"]], outputKeys: ["ok", "status", "statusText", "response"] },
4822
4943
  "hubspotCreateCompany": { fields: [["company", "object"], ["enabledProperties", "array"]], outputKeys: ["companyId"] },
4823
4944
  "hubspotCreateContact": { fields: [["contact", "object"], ["enabledProperties", "array"], ["companyDomain", "string"]], outputKeys: ["contactId"] },
4824
4945
  "hubspotGetCompany": { fields: [["searchBy", ["domain", "id"]], ["companyDomain", "string"], ["companyId", "string"], ["additionalProperties", "array"]], outputKeys: ["company"] },