@mastra/mysql 0.6.0 → 0.7.0-alpha.1

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
@@ -2837,15 +2837,28 @@ var ExperimentsMySQL = class ExperimentsMySQL extends ExperimentsStorage {
2837
2837
  * Returns default index definitions for the experiments domain tables.
2838
2838
  */
2839
2839
  static getDefaultIndexDefs(_prefix = "") {
2840
- return [{
2841
- name: "idx_experiments_org_project",
2842
- table: TABLE_EXPERIMENTS,
2843
- columns: ["organizationId", "projectId"]
2844
- }, {
2845
- name: "idx_experiment_results_org_project",
2846
- table: TABLE_EXPERIMENT_RESULTS,
2847
- columns: ["organizationId", "projectId"]
2848
- }];
2840
+ return [
2841
+ {
2842
+ name: "idx_experiments_grouping",
2843
+ table: TABLE_EXPERIMENTS,
2844
+ columns: [
2845
+ "experimentSetId",
2846
+ "comparisonId",
2847
+ "variantId",
2848
+ "trialIndex"
2849
+ ]
2850
+ },
2851
+ {
2852
+ name: "idx_experiments_org_project",
2853
+ table: TABLE_EXPERIMENTS,
2854
+ columns: ["organizationId", "projectId"]
2855
+ },
2856
+ {
2857
+ name: "idx_experiment_results_org_project",
2858
+ table: TABLE_EXPERIMENT_RESULTS,
2859
+ columns: ["organizationId", "projectId"]
2860
+ }
2861
+ ];
2849
2862
  }
2850
2863
  /**
2851
2864
  * Exports DDL statements for all managed tables.
@@ -2901,7 +2914,13 @@ var ExperimentsMySQL = class ExperimentsMySQL extends ExperimentsStorage {
2901
2914
  ifNotExists: [
2902
2915
  "agentVersion",
2903
2916
  "organizationId",
2904
- "projectId"
2917
+ "projectId",
2918
+ "provenance",
2919
+ "runnerAttestation",
2920
+ "experimentSetId",
2921
+ "comparisonId",
2922
+ "variantId",
2923
+ "trialIndex"
2905
2924
  ]
2906
2925
  });
2907
2926
  await this.operations.alterTable({
@@ -2933,6 +2952,12 @@ var ExperimentsMySQL = class ExperimentsMySQL extends ExperimentsStorage {
2933
2952
  name: row.name ?? void 0,
2934
2953
  description: row.description ?? void 0,
2935
2954
  metadata: parseJSON$2(row.metadata),
2955
+ provenance: parseJSON$2(row.provenance) ?? null,
2956
+ runnerAttestation: parseJSON$2(row.runnerAttestation) ?? null,
2957
+ experimentSetId: row.experimentSetId ?? null,
2958
+ comparisonId: row.comparisonId ?? null,
2959
+ variantId: row.variantId ?? null,
2960
+ trialIndex: row.trialIndex ?? null,
2936
2961
  status: row.status,
2937
2962
  totalItems: row.totalItems,
2938
2963
  succeededCount: row.succeededCount,
@@ -2984,6 +3009,12 @@ var ExperimentsMySQL = class ExperimentsMySQL extends ExperimentsStorage {
2984
3009
  name: input.name ?? null,
2985
3010
  description: input.description ?? null,
2986
3011
  metadata: input.metadata ? JSON.stringify(input.metadata) : null,
3012
+ provenance: input.provenance ? JSON.stringify(input.provenance) : null,
3013
+ runnerAttestation: input.runnerAttestation ? JSON.stringify(input.runnerAttestation) : null,
3014
+ experimentSetId: input.experimentSetId ?? null,
3015
+ comparisonId: input.comparisonId ?? null,
3016
+ variantId: input.variantId ?? null,
3017
+ trialIndex: input.trialIndex ?? null,
2987
3018
  status: "pending",
2988
3019
  totalItems: input.totalItems,
2989
3020
  succeededCount: 0,
@@ -3007,6 +3038,12 @@ var ExperimentsMySQL = class ExperimentsMySQL extends ExperimentsStorage {
3007
3038
  name: input.name,
3008
3039
  description: input.description,
3009
3040
  metadata: input.metadata,
3041
+ provenance: input.provenance ?? null,
3042
+ runnerAttestation: input.runnerAttestation ?? null,
3043
+ experimentSetId: input.experimentSetId ?? null,
3044
+ comparisonId: input.comparisonId ?? null,
3045
+ variantId: input.variantId ?? null,
3046
+ trialIndex: input.trialIndex ?? null,
3010
3047
  status: "pending",
3011
3048
  totalItems: input.totalItems,
3012
3049
  succeededCount: 0,
@@ -3103,6 +3140,22 @@ var ExperimentsMySQL = class ExperimentsMySQL extends ExperimentsStorage {
3103
3140
  conditions.push(`${quoteIdentifier("status", "column name")} = ?`);
3104
3141
  params.push(args.status);
3105
3142
  }
3143
+ if (args.experimentSetId !== void 0) {
3144
+ conditions.push(`${quoteIdentifier("experimentSetId", "column name")} = ?`);
3145
+ params.push(args.experimentSetId);
3146
+ }
3147
+ if (args.comparisonId !== void 0) {
3148
+ conditions.push(`${quoteIdentifier("comparisonId", "column name")} = ?`);
3149
+ params.push(args.comparisonId);
3150
+ }
3151
+ if (args.variantId !== void 0) {
3152
+ conditions.push(`${quoteIdentifier("variantId", "column name")} = ?`);
3153
+ params.push(args.variantId);
3154
+ }
3155
+ if (args.trialIndex !== void 0) {
3156
+ conditions.push(`${quoteIdentifier("trialIndex", "column name")} = ?`);
3157
+ params.push(args.trialIndex);
3158
+ }
3106
3159
  if (args.filters) {
3107
3160
  const { organizationId, projectId } = args.filters;
3108
3161
  if (organizationId !== void 0) {
@@ -4868,9 +4921,17 @@ var MemoryMySQL = class MemoryMySQL extends MemoryStorage {
4868
4921
  if (row.type && row.type !== "v2") message.type = row.type;
4869
4922
  return message;
4870
4923
  }
4871
- async fetchMessagesForThread(threadId, limit) {
4872
- let sql = `SELECT id, thread_id, content, role, type, createdAt, resourceId FROM ${formatTableName(TABLE_MESSAGES)} WHERE ${quoteIdentifier("thread_id", "column name")} = ? ORDER BY ${quoteIdentifier("createdAt", "column name")} ASC`;
4873
- const params = [threadId];
4924
+ /**
4925
+ * Loads a thread's messages in chronological order.
4926
+ *
4927
+ * @param threadId - Thread to read.
4928
+ * @param limit - Optional cap on the number of rows.
4929
+ * @param resourceId - When set, returns only the rows owned by that resource.
4930
+ */
4931
+ async fetchMessagesForThread(threadId, limit, resourceId) {
4932
+ const resourceCondition = resourceId ? ` AND ${quoteIdentifier("resourceId", "column name")} = ?` : "";
4933
+ let sql = `SELECT id, thread_id, content, role, type, createdAt, resourceId FROM ${formatTableName(TABLE_MESSAGES)} WHERE ${quoteIdentifier("thread_id", "column name")} = ?${resourceCondition} ORDER BY ${quoteIdentifier("createdAt", "column name")} ASC`;
4934
+ const params = resourceId ? [threadId, resourceId] : [threadId];
4874
4935
  if (limit && limit > 0) {
4875
4936
  sql += ` LIMIT ?`;
4876
4937
  params.push(limit);
@@ -4881,15 +4942,20 @@ var MemoryMySQL = class MemoryMySQL extends MemoryStorage {
4881
4942
  /**
4882
4943
  * Fetches included messages by ID, discovering their thread automatically.
4883
4944
  * This handles cross-thread includes where the include item doesn't specify a threadId.
4945
+ *
4946
+ * @param include - Message ids to pin, each with an optional before/after window.
4947
+ * @param resourceId - When set, restricts both the pinned messages and their context
4948
+ * to that resource so an id from another resource returns nothing.
4884
4949
  */
4885
- async _getIncludedMessages({ include }) {
4950
+ async _getIncludedMessages({ include, resourceId }) {
4886
4951
  if (!include || include.length === 0) return null;
4887
4952
  const tableName = formatTableName(TABLE_MESSAGES);
4888
4953
  const selectColumns = `id, thread_id, content, role, type, createdAt, resourceId`;
4954
+ const resourceCondition = resourceId ? ` AND m.${quoteIdentifier("resourceId", "column name")} = ?` : "";
4889
4955
  const targetIds = include.map((inc) => inc.id).filter(Boolean);
4890
4956
  if (targetIds.length === 0) return null;
4891
4957
  const idPlaceholders = targetIds.map(() => "?").join(", ");
4892
- const [targetRows] = await this.pool.execute(`SELECT id, thread_id, createdAt FROM ${tableName} WHERE id IN (${idPlaceholders})`, targetIds);
4958
+ const [targetRows] = await this.pool.execute(`SELECT id, thread_id, createdAt FROM ${tableName} WHERE id IN (${idPlaceholders})${resourceId ? ` AND ${quoteIdentifier("resourceId", "column name")} = ?` : ""}`, resourceId ? [...targetIds, resourceId] : targetIds);
4893
4959
  if (!targetRows || targetRows.length === 0) return null;
4894
4960
  const targetMap = new Map(targetRows.map((r) => [r.id, {
4895
4961
  threadId: r.thread_id,
@@ -4907,21 +4973,23 @@ var MemoryMySQL = class MemoryMySQL extends MemoryStorage {
4907
4973
  SELECT ${selectColumns}
4908
4974
  FROM ${tableName} m
4909
4975
  WHERE m.thread_id = ?
4910
- AND m.createdAt <= ?
4976
+ AND m.createdAt <= ?${resourceCondition}
4911
4977
  ORDER BY m.createdAt DESC, m.id DESC
4912
4978
  LIMIT ${prevLimit}
4913
4979
  )`);
4914
4980
  params.push(target.threadId, target.createdAt);
4981
+ if (resourceId) params.push(resourceId);
4915
4982
  if (nextLimit > 0) {
4916
4983
  unionQueries.push(`(
4917
4984
  SELECT ${selectColumns}
4918
4985
  FROM ${tableName} m
4919
4986
  WHERE m.thread_id = ?
4920
- AND m.createdAt > ?
4987
+ AND m.createdAt > ?${resourceCondition}
4921
4988
  ORDER BY m.createdAt ASC, m.id ASC
4922
4989
  LIMIT ${nextLimit}
4923
4990
  )`);
4924
4991
  params.push(target.threadId, target.createdAt);
4992
+ if (resourceId) params.push(resourceId);
4925
4993
  }
4926
4994
  }
4927
4995
  if (unionQueries.length === 0) return null;
@@ -4929,7 +4997,17 @@ var MemoryMySQL = class MemoryMySQL extends MemoryStorage {
4929
4997
  const [rows] = await this.pool.execute(finalQuery, params);
4930
4998
  return rows;
4931
4999
  }
4932
- async collectIncludeMessages({ threadId, include, messagesByThread }) {
5000
+ /**
5001
+ * Resolves include items against loaded threads, adding each pinned message and its
5002
+ * before/after window.
5003
+ *
5004
+ * @param threadId - Thread used when an include item names no thread of its own.
5005
+ * @param include - Message ids to pin, each with an optional before/after window.
5006
+ * @param messagesByThread - Cache of thread snapshots, reused and filled as threads load.
5007
+ * @param resourceId - When set, restricts both the pinned messages and their context
5008
+ * to that resource so an id from another resource returns nothing.
5009
+ */
5010
+ async collectIncludeMessages({ threadId, include, messagesByThread, resourceId }) {
4933
5011
  if (!include?.length) return [];
4934
5012
  const includeMessages = [];
4935
5013
  const seenIds = /* @__PURE__ */ new Set();
@@ -4937,18 +5015,18 @@ var MemoryMySQL = class MemoryMySQL extends MemoryStorage {
4937
5015
  const resolvedThreadIds = /* @__PURE__ */ new Map();
4938
5016
  if (unresolvedIds.length > 0) {
4939
5017
  const placeholders = unresolvedIds.map(() => "?").join(", ");
4940
- const [rows] = await this.pool.execute(`SELECT id, thread_id FROM ${formatTableName(TABLE_MESSAGES)} WHERE id IN (${placeholders})`, unresolvedIds);
5018
+ const [rows] = await this.pool.execute(`SELECT id, thread_id FROM ${formatTableName(TABLE_MESSAGES)} WHERE id IN (${placeholders})${resourceId ? ` AND ${quoteIdentifier("resourceId", "column name")} = ?` : ""}`, resourceId ? [...unresolvedIds, resourceId] : unresolvedIds);
4941
5019
  for (const row of rows) resolvedThreadIds.set(row.id, row.thread_id);
4942
5020
  }
4943
5021
  for (const inc of include) {
4944
5022
  const targetThreadId = inc.threadId ?? resolvedThreadIds.get(inc.id) ?? threadId;
4945
5023
  let threadMessages = messagesByThread.get(targetThreadId);
4946
5024
  if (!threadMessages) {
4947
- threadMessages = (await this.fetchMessagesForThread(targetThreadId)).map((row) => this.mapMessage(row));
5025
+ threadMessages = (await this.fetchMessagesForThread(targetThreadId, void 0, resourceId)).map((row) => this.mapMessage(row));
4948
5026
  messagesByThread.set(targetThreadId, threadMessages);
4949
5027
  }
4950
5028
  if (!threadMessages.some((message) => message.id === inc.id) || (inc.withPreviousMessages ?? 0) > 0 || (inc.withNextMessages ?? 0) > 0 || threadMessages.length < (inc.withNextMessages ?? 0) + (inc.withPreviousMessages ?? 0) + 1) {
4951
- threadMessages = (await this.fetchMessagesForThread(targetThreadId)).map((row) => this.mapMessage(row));
5029
+ threadMessages = (await this.fetchMessagesForThread(targetThreadId, void 0, resourceId)).map((row) => this.mapMessage(row));
4952
5030
  messagesByThread.set(targetThreadId, threadMessages);
4953
5031
  }
4954
5032
  const targetIndex = threadMessages.findIndex((msg) => msg.id === inc.id);
@@ -5065,12 +5143,16 @@ var MemoryMySQL = class MemoryMySQL extends MemoryStorage {
5065
5143
  hasMore: perPageInput === false ? false : offset + perPageNormalized < total
5066
5144
  };
5067
5145
  } catch (error) {
5068
- throw new MastraError({
5069
- id: "MYSQL_MEMORY_LIST_THREADS_FAILED",
5146
+ if (error instanceof MastraError && error.category === ErrorCategory.USER) throw error;
5147
+ const mastraError = new MastraError({
5148
+ id: createStorageErrorId("MYSQL", "LIST_THREADS", "FAILED"),
5070
5149
  domain: ErrorDomain.STORAGE,
5071
5150
  category: ErrorCategory.THIRD_PARTY,
5072
5151
  details: { filter: JSON.stringify(filter ?? {}) }
5073
5152
  }, error);
5153
+ this.logger?.error?.(mastraError.toString());
5154
+ this.logger?.trackException?.(mastraError);
5155
+ throw mastraError;
5074
5156
  }
5075
5157
  }
5076
5158
  async getThreadsByResourceId(args) {
@@ -5538,7 +5620,10 @@ var MemoryMySQL = class MemoryMySQL extends MemoryStorage {
5538
5620
  hasMore: false
5539
5621
  };
5540
5622
  if (perPage === 0 && include && include.length > 0) {
5541
- const includeRows = await this._getIncludedMessages({ include });
5623
+ const includeRows = await this._getIncludedMessages({
5624
+ include,
5625
+ resourceId
5626
+ });
5542
5627
  if (!includeRows || includeRows.length === 0) return {
5543
5628
  messages: [],
5544
5629
  total: 0,
@@ -5576,7 +5661,8 @@ var MemoryMySQL = class MemoryMySQL extends MemoryStorage {
5576
5661
  const includeMessages = await this.collectIncludeMessages({
5577
5662
  threadId: primaryThreadId,
5578
5663
  include,
5579
- messagesByThread
5664
+ messagesByThread,
5665
+ resourceId
5580
5666
  });
5581
5667
  const combinedMap = /* @__PURE__ */ new Map();
5582
5668
  for (const msg of paginatedMain) combinedMap.set(msg.id, msg);
@@ -5596,8 +5682,9 @@ var MemoryMySQL = class MemoryMySQL extends MemoryStorage {
5596
5682
  hasMore: metadataFilter || !include?.length || mainThreadMessageCount < total ? baseHasMore : false
5597
5683
  };
5598
5684
  } catch (error) {
5685
+ if (error instanceof MastraError && error.category === ErrorCategory.USER) throw error;
5599
5686
  const mastraError = new MastraError({
5600
- id: "MYSQL_MEMORY_GET_MESSAGES_PAGINATED_FAILED",
5687
+ id: createStorageErrorId("MYSQL", "LIST_MESSAGES", "FAILED"),
5601
5688
  domain: ErrorDomain.STORAGE,
5602
5689
  category: ErrorCategory.THIRD_PARTY,
5603
5690
  details: {
@@ -5608,13 +5695,7 @@ var MemoryMySQL = class MemoryMySQL extends MemoryStorage {
5608
5695
  }, error);
5609
5696
  this.logger?.error?.(mastraError.toString());
5610
5697
  this.logger?.trackException?.(mastraError);
5611
- return {
5612
- messages: [],
5613
- total: 0,
5614
- page,
5615
- perPage,
5616
- hasMore: false
5617
- };
5698
+ throw mastraError;
5618
5699
  }
5619
5700
  }
5620
5701
  async listMessagesByResourceId(args) {
@@ -5669,7 +5750,7 @@ var MemoryMySQL = class MemoryMySQL extends MemoryStorage {
5669
5750
  if (include && include.length > 0) {
5670
5751
  const validInclude = (await Promise.all(include.map(async (inc) => {
5671
5752
  if (inc.threadId) return inc;
5672
- const [msgRows] = await this.pool.execute(`SELECT thread_id FROM ${tableName} WHERE id = ? LIMIT 1`, [inc.id]);
5753
+ const [msgRows] = await this.pool.execute(`SELECT thread_id FROM ${tableName} WHERE id = ? AND ${quoteIdentifier("resourceId", "column name")} = ? LIMIT 1`, [inc.id, resourceId]);
5673
5754
  const threadId = msgRows?.[0]?.thread_id;
5674
5755
  return threadId ? {
5675
5756
  ...inc,
@@ -5681,7 +5762,8 @@ var MemoryMySQL = class MemoryMySQL extends MemoryStorage {
5681
5762
  const includeMessages = await this.collectIncludeMessages({
5682
5763
  threadId: validInclude[0].threadId,
5683
5764
  include: validInclude,
5684
- messagesByThread
5765
+ messagesByThread,
5766
+ resourceId
5685
5767
  });
5686
5768
  for (const includeMsg of includeMessages) if (!messageIds.has(includeMsg.id)) {
5687
5769
  messages.push(includeMsg);
@@ -5706,21 +5788,16 @@ var MemoryMySQL = class MemoryMySQL extends MemoryStorage {
5706
5788
  hasMore
5707
5789
  };
5708
5790
  } catch (error) {
5791
+ if (error instanceof MastraError && error.category === ErrorCategory.USER) throw error;
5709
5792
  const mastraError = new MastraError({
5710
- id: createStorageErrorId("MYSQL", "LIST_MESSAGES", "FAILED"),
5793
+ id: createStorageErrorId("MYSQL", "LIST_MESSAGES_BY_RESOURCE_ID", "FAILED"),
5711
5794
  domain: ErrorDomain.STORAGE,
5712
5795
  category: ErrorCategory.THIRD_PARTY,
5713
5796
  details: { resourceId }
5714
5797
  }, error);
5715
5798
  this.logger?.error?.(mastraError.toString());
5716
5799
  this.logger?.trackException?.(mastraError);
5717
- return {
5718
- messages: [],
5719
- total: 0,
5720
- page,
5721
- perPage: perPageForResponse,
5722
- hasMore: false
5723
- };
5800
+ throw mastraError;
5724
5801
  }
5725
5802
  }
5726
5803
  async getResourceById({ resourceId }) {