@mindstudio-ai/agent 0.1.10 → 0.1.12

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.
@@ -1523,7 +1523,15 @@ var init_sql = __esm({
1523
1523
  "src/db/sql.ts"() {
1524
1524
  "use strict";
1525
1525
  USER_PREFIX = "@@user@@";
1526
- SYSTEM_COLUMNS = /* @__PURE__ */ new Set(["id", "createdAt", "updatedAt", "lastUpdatedBy"]);
1526
+ SYSTEM_COLUMNS = /* @__PURE__ */ new Set([
1527
+ "id",
1528
+ "created_at",
1529
+ "createdAt",
1530
+ "updated_at",
1531
+ "updatedAt",
1532
+ "last_updated_by",
1533
+ "lastUpdatedBy"
1534
+ ]);
1527
1535
  }
1528
1536
  });
1529
1537
 
@@ -1968,8 +1976,7 @@ var init_predicate = __esm({
1968
1976
  return PARSE_FAILED;
1969
1977
  }
1970
1978
  /**
1971
- * Attempt to resolve a closure variable by invoking the original function
1972
- * with a recording Proxy and inspecting what values it compares against.
1979
+ * Attempt to resolve a closure variable's value.
1973
1980
  *
1974
1981
  * This handles the common pattern:
1975
1982
  * ```ts
@@ -1977,40 +1984,28 @@ var init_predicate = __esm({
1977
1984
  * orders.filter(o => o.requestedBy === userId)
1978
1985
  * ```
1979
1986
  *
1980
- * The Proxy captures property accesses on the parameter and we can then
1981
- * extract the comparison value from the function's behavior. However,
1982
- * this approach has limitations if the function throws, has side effects,
1983
- * or uses the variable in a non-comparison context, we fall back to JS.
1987
+ * Closure variable resolution is fundamentally limited in JavaScript
1988
+ * we can't access another function's closure scope from outside without
1989
+ * `eval`. The `===` operator can't be overridden via Proxy or
1990
+ * Symbol.toPrimitive, so we can't intercept comparisons.
1991
+ *
1992
+ * For now, this falls back to JS execution. The predicate still works
1993
+ * correctly — it just scans all rows instead of generating SQL.
1994
+ * This is the most common reason for JS fallback in practice, since
1995
+ * almost every real-world filter references a variable like `userId`.
1996
+ *
1997
+ * A future improvement could accept an explicit `vars` argument:
1998
+ * ```ts
1999
+ * orders.filter(o => o.requestedBy === $userId, { $userId: auth.userId })
2000
+ * ```
1984
2001
  */
1985
2002
  resolveClosureVariable() {
1986
- const identToken = this.advance();
1987
- let closureExpr = identToken.value;
2003
+ this.advance();
1988
2004
  while (this.match("dot") && this.tokens[this.pos + 1]?.type === "identifier") {
1989
2005
  this.advance();
1990
- closureExpr += "." + this.advance().value;
1991
- }
1992
- try {
1993
- const MARKER = /* @__PURE__ */ Symbol("field_access_marker");
1994
- const accessed = [];
1995
- const proxy = new Proxy(
1996
- {},
1997
- {
1998
- get(_, prop) {
1999
- accessed.push(prop);
2000
- return new Proxy(() => MARKER, {
2001
- get(_2, nestedProp) {
2002
- accessed.push(nestedProp);
2003
- return MARKER;
2004
- }
2005
- });
2006
- }
2007
- }
2008
- );
2009
- void proxy;
2010
- return PARSE_FAILED;
2011
- } catch {
2012
- return PARSE_FAILED;
2006
+ this.advance();
2013
2007
  }
2008
+ return PARSE_FAILED;
2014
2009
  }
2015
2010
  /**
2016
2011
  * Look ahead to check if the next tokens form `.includes(`.
@@ -2169,6 +2164,76 @@ var init_query = __esm({
2169
2164
  return map;
2170
2165
  }
2171
2166
  // -------------------------------------------------------------------------
2167
+ // Batch compilation — used by db.batch() to extract SQL without executing
2168
+ // -------------------------------------------------------------------------
2169
+ /**
2170
+ * @internal Compile this query into a SqlQuery for batch execution.
2171
+ *
2172
+ * Returns the compiled SQL query (if all predicates compile to SQL),
2173
+ * or null (if JS fallback is needed). In the fallback case, a bare
2174
+ * `SELECT *` is returned as `fallbackQuery` so the batch can fetch
2175
+ * all rows and this query can filter them in JS post-fetch.
2176
+ */
2177
+ _compile() {
2178
+ const compiled = this._compilePredicates();
2179
+ const sortField = this._sortAccessor ? extractFieldName(this._sortAccessor) : void 0;
2180
+ if (compiled.allSql) {
2181
+ const query = buildSelect(this._config.tableName, {
2182
+ where: compiled.sqlWhere || void 0,
2183
+ orderBy: sortField ?? void 0,
2184
+ desc: this._reversed,
2185
+ limit: this._limit,
2186
+ offset: this._offset
2187
+ });
2188
+ return { query, fallbackQuery: null, config: this._config };
2189
+ }
2190
+ const fallbackQuery = buildSelect(this._config.tableName);
2191
+ return {
2192
+ query: null,
2193
+ fallbackQuery,
2194
+ config: this._config,
2195
+ predicates: this._predicates,
2196
+ sortAccessor: this._sortAccessor,
2197
+ reversed: this._reversed,
2198
+ limit: this._limit,
2199
+ offset: this._offset
2200
+ };
2201
+ }
2202
+ /**
2203
+ * @internal Process raw SQL results into typed rows. Used by db.batch()
2204
+ * after executing the compiled query.
2205
+ *
2206
+ * For SQL-compiled queries: just deserialize the rows.
2207
+ * For JS-fallback queries: filter, sort, and slice in JS.
2208
+ */
2209
+ static _processResults(result, compiled) {
2210
+ const rows = result.rows.map(
2211
+ (row) => deserializeRow(
2212
+ row,
2213
+ compiled.config.columns
2214
+ )
2215
+ );
2216
+ if (compiled.query) return rows;
2217
+ let filtered = compiled.predicates ? rows.filter((row) => compiled.predicates.every((pred) => pred(row))) : rows;
2218
+ if (compiled.sortAccessor) {
2219
+ const accessor = compiled.sortAccessor;
2220
+ const reversed = compiled.reversed ?? false;
2221
+ filtered.sort((a, b) => {
2222
+ const aVal = accessor(a);
2223
+ const bVal = accessor(b);
2224
+ if (aVal < bVal) return reversed ? 1 : -1;
2225
+ if (aVal > bVal) return reversed ? -1 : 1;
2226
+ return 0;
2227
+ });
2228
+ }
2229
+ if (compiled.offset != null || compiled.limit != null) {
2230
+ const start = compiled.offset ?? 0;
2231
+ const end = compiled.limit != null ? start + compiled.limit : void 0;
2232
+ filtered = filtered.slice(start, end);
2233
+ }
2234
+ return filtered;
2235
+ }
2236
+ // -------------------------------------------------------------------------
2172
2237
  // PromiseLike
2173
2238
  // -------------------------------------------------------------------------
2174
2239
  then(onfulfilled, onrejected) {
@@ -2418,7 +2483,49 @@ function createDb(databases, executeBatch) {
2418
2483
  hours: (n) => n * 36e5,
2419
2484
  minutes: (n) => n * 6e4,
2420
2485
  ago: (ms) => Date.now() - ms,
2421
- fromNow: (ms) => Date.now() + ms
2486
+ fromNow: (ms) => Date.now() + ms,
2487
+ // --- Batch execution ---
2488
+ batch: ((...queries) => {
2489
+ return (async () => {
2490
+ const compiled = queries.map((q) => {
2491
+ if (!(q instanceof Query)) {
2492
+ throw new MindStudioError(
2493
+ "db.batch() only accepts Query objects (from .filter(), .sortBy(), etc.)",
2494
+ "invalid_batch_query",
2495
+ 400
2496
+ );
2497
+ }
2498
+ return q._compile();
2499
+ });
2500
+ const groups = /* @__PURE__ */ new Map();
2501
+ for (let i = 0; i < compiled.length; i++) {
2502
+ const c = compiled[i];
2503
+ const dbId = c.config.databaseId;
2504
+ const sqlQuery = c.query ?? c.fallbackQuery;
2505
+ if (!groups.has(dbId)) groups.set(dbId, []);
2506
+ groups.get(dbId).push({ index: i, sqlQuery });
2507
+ }
2508
+ const allResults = new Array(compiled.length);
2509
+ await Promise.all(
2510
+ Array.from(groups.entries()).map(async ([dbId, entries]) => {
2511
+ const sqlQueries = entries.map((e) => e.sqlQuery);
2512
+ const results = await executeBatch(dbId, sqlQueries);
2513
+ for (let i = 0; i < entries.length; i++) {
2514
+ allResults[entries[i].index] = results[i];
2515
+ }
2516
+ })
2517
+ );
2518
+ return compiled.map((c, i) => {
2519
+ const result = allResults[i];
2520
+ if (!c.query && c.predicates?.length) {
2521
+ console.warn(
2522
+ `[mindstudio] db.batch(): filter on ${c.config.tableName} could not be compiled to SQL \u2014 processing in JS`
2523
+ );
2524
+ }
2525
+ return Query._processResults(result, c);
2526
+ });
2527
+ })();
2528
+ })
2422
2529
  };
2423
2530
  }
2424
2531
  function resolveTable(databases, tableName, databaseHint) {
@@ -2473,6 +2580,7 @@ var init_db = __esm({
2473
2580
  "use strict";
2474
2581
  init_errors();
2475
2582
  init_table();
2583
+ init_query();
2476
2584
  init_table();
2477
2585
  }
2478
2586
  });
@@ -3238,10 +3346,12 @@ var init_client = __esm({
3238
3346
  );
3239
3347
  }
3240
3348
  if (!res.ok) {
3349
+ const errorBody = await res.json().catch(() => ({}));
3241
3350
  throw new MindStudioError(
3242
- `Poll request failed: ${res.status} ${res.statusText}`,
3243
- "poll_error",
3244
- res.status
3351
+ errorBody.message ?? errorBody.error ?? `Poll request failed: ${res.status} ${res.statusText}`,
3352
+ errorBody.code ?? "poll_error",
3353
+ res.status,
3354
+ errorBody
3245
3355
  );
3246
3356
  }
3247
3357
  const poll = await res.json();
@@ -3506,12 +3616,24 @@ var init_client = __esm({
3506
3616
  });
3507
3617
  if (!res.ok) {
3508
3618
  let message = `Database query failed: ${res.status} ${res.statusText}`;
3619
+ let code = "db_query_error";
3509
3620
  try {
3510
- const body = await res.json();
3511
- if (body.error) message = body.error;
3621
+ const text = await res.text();
3622
+ try {
3623
+ const body = JSON.parse(text);
3624
+ const errMsg = body.error ?? body.message ?? body.details;
3625
+ if (errMsg) message = errMsg;
3626
+ if (body.code) code = body.code;
3627
+ } catch {
3628
+ if (text && text.length < 500) message = text;
3629
+ }
3512
3630
  } catch {
3513
3631
  }
3514
- throw new MindStudioError(message, "db_query_error", res.status);
3632
+ throw new MindStudioError(
3633
+ `[db] ${message}`,
3634
+ code,
3635
+ res.status
3636
+ );
3515
3637
  }
3516
3638
  const data = await res.json();
3517
3639
  return data.results;
@@ -3556,7 +3678,14 @@ var init_client = __esm({
3556
3678
  hours: (n) => n * 36e5,
3557
3679
  minutes: (n) => n * 6e4,
3558
3680
  ago: (ms) => Date.now() - ms,
3559
- fromNow: (ms) => Date.now() + ms
3681
+ fromNow: (ms) => Date.now() + ms,
3682
+ // Batch needs context — hydrate first, then delegate to real db
3683
+ batch: ((...queries) => {
3684
+ return (async () => {
3685
+ await agent.ensureContext();
3686
+ return agent._db.batch(...queries);
3687
+ })();
3688
+ })
3560
3689
  };
3561
3690
  }
3562
3691
  // -------------------------------------------------------------------------
@@ -3688,10 +3817,12 @@ var init_client = __esm({
3688
3817
  headers: options.type ? { "Content-Type": options.type } : {}
3689
3818
  });
3690
3819
  if (!res.ok) {
3820
+ const errorBody = await res.json().catch(() => ({}));
3691
3821
  throw new MindStudioError(
3692
- `Upload failed: ${res.status} ${res.statusText}`,
3693
- "upload_error",
3694
- res.status
3822
+ errorBody.message ?? errorBody.error ?? `Upload failed: ${res.status} ${res.statusText}`,
3823
+ errorBody.code ?? "upload_error",
3824
+ res.status,
3825
+ errorBody
3695
3826
  );
3696
3827
  }
3697
3828
  return { url: data.url };
@@ -3761,7 +3892,7 @@ async function startMcpServer(options) {
3761
3892
  capabilities: { tools: {} },
3762
3893
  serverInfo: {
3763
3894
  name: "mindstudio-agent",
3764
- version: "0.1.10"
3895
+ version: "0.1.12"
3765
3896
  },
3766
3897
  instructions: "Welcome to MindStudio \u2014 a platform with 200+ AI models, 850+ third-party integrations, and pre-built agents.\n\nGetting started:\n1. Call `listAgents` to verify your connection and see available agents.\n2. Call `changeName` to set your display name \u2014 use your name or whatever your user calls you. This is how you'll appear in MindStudio request logs.\n3. If you have a profile picture or icon, call `uploadFile` to upload it, then `changeProfilePicture` with the returned URL. This helps users identify your requests in their logs.\n4. Call `listActions` to discover all available actions.\n\nThen use the tools to generate text, images, video, audio, search the web, work with data sources, run agents, and more.\n\nImportant:\n- AI-powered actions (text generation, image generation, video, audio, etc.) cost money. Before running these, call `estimateActionCost` and confirm with the user before proceeding \u2014 unless they've explicitly told you to go ahead.\n- Not all agents from `listAgents` are configured for API use. Do not try to run an agent just because it appears in the list \u2014 it will likely fail. Only run agents the user specifically asks you to run."
3767
3898
  });
@@ -4581,7 +4712,7 @@ function isNewerVersion(current, latest) {
4581
4712
  return false;
4582
4713
  }
4583
4714
  async function checkForUpdate() {
4584
- const currentVersion = "0.1.10";
4715
+ const currentVersion = "0.1.12";
4585
4716
  if (!currentVersion) return null;
4586
4717
  try {
4587
4718
  const { loadConfig: loadConfig2, saveConfig: saveConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
@@ -4610,7 +4741,7 @@ async function checkForUpdate() {
4610
4741
  }
4611
4742
  }
4612
4743
  function printUpdateNotice(latestVersion) {
4613
- const currentVersion = "0.1.10";
4744
+ const currentVersion = "0.1.12";
4614
4745
  process.stderr.write(
4615
4746
  `
4616
4747
  ${ansi.cyanBright("Update available")} ${ansi.gray(currentVersion + " \u2192")} ${ansi.cyanBold(latestVersion)}
@@ -4665,7 +4796,7 @@ async function cmdLogin(options) {
4665
4796
  process.stderr.write("\n");
4666
4797
  printLogo();
4667
4798
  process.stderr.write("\n");
4668
- const ver = "0.1.10";
4799
+ const ver = "0.1.12";
4669
4800
  process.stderr.write(
4670
4801
  ` ${ansi.bold("MindStudio Agent")} ${ver ? " " + ansi.gray("v" + ver) : ""}
4671
4802
  `
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mindstudio-ai/agent",
3
- "version": "0.1.10",
3
+ "version": "0.1.12",
4
4
  "description": "TypeScript SDK for MindStudio direct step execution",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",