@mastra/mysql 0.3.0-alpha.1 → 0.3.1-alpha.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/CHANGELOG.md CHANGED
@@ -1,5 +1,93 @@
1
1
  # @mastra/mysql
2
2
 
3
+ ## 0.3.1-alpha.0
4
+
5
+ ### Patch Changes
6
+
7
+ - Fixed workflow snapshots and AI spans creating duplicate records instead of updating in place. Each workflow step previously inserted a new row, causing unbounded table growth and degraded read performance. ([#18460](https://github.com/mastra-ai/mastra/pull/18460))
8
+
9
+ - Fixed workflow runs preserving their original creation time when re-persisted in MySQL storage, including concurrent saves. ([#18004](https://github.com/mastra-ai/mastra/pull/18004))
10
+
11
+ - Updated dependencies [[`bf3fe49`](https://github.com/mastra-ai/mastra/commit/bf3fe49f9467dbbdb8f9eaf74e0f7971ffb19559), [`24ceaea`](https://github.com/mastra-ai/mastra/commit/24ceaea0bdd8609cabbab764380608ca6621a194), [`6ccf67b`](https://github.com/mastra-ai/mastra/commit/6ccf67bf075753754927a57bc2e1734ba2c820c5), [`825d8de`](https://github.com/mastra-ai/mastra/commit/825d8def9fa64c2bcc3d8dd6b49e09342c3ac5c7), [`ffa09e7`](https://github.com/mastra-ai/mastra/commit/ffa09e772a5c92270eabe2090fc42d45bd8ec4b7), [`461a7c5`](https://github.com/mastra-ai/mastra/commit/461a7c501449295287f4f0ee4b0b42344f39fcf8), [`4211472`](https://github.com/mastra-ai/mastra/commit/4211472a5a2bd319c60cd2e42d9109c3eef7ac1c), [`9e45902`](https://github.com/mastra-ai/mastra/commit/9e4590208e745055cecca202e2db0e5c65e17d3c), [`5c0df77`](https://github.com/mastra-ai/mastra/commit/5c0df776c40efa420f8c07a2f3ee66010296618e)]:
12
+ - @mastra/core@1.47.0-alpha.3
13
+
14
+ ## 0.3.0
15
+
16
+ ### Minor Changes
17
+
18
+ - The MySQL store now rejects item-level tool mocks with a clear error instead of silently dropping them. Tool mock persistence is not yet supported on MySQL, so saving a dataset item with `toolMocks` (or an experiment result with a `toolMockReport`) fails fast rather than discarding the data. ([#18036](https://github.com/mastra-ai/mastra/pull/18036))
19
+
20
+ ### Patch Changes
21
+
22
+ - Added multi-tenant scoping columns (`organizationId`, `projectId`) to the experiments domain so experiment records and per-item results inherit the tenancy bucket of their parent dataset. ([#18388](https://github.com/mastra-ai/mastra/pull/18388))
23
+
24
+ `Experiment`, `ExperimentResult`, `CreateExperimentInput`, and `AddExperimentResultInput` now carry optional `organizationId` / `projectId` fields. `ListExperimentsInput` and `ListExperimentResultsInput` gain a `filters: ExperimentTenancyFilters` block (mirrors `DatasetTenancyFilters`) for scoping queries within a `(organizationId, projectId)` bucket. Tenancy is hydrated from the parent dataset on `createExperiment` and denormalized onto each `ExperimentResult` for efficient tenancy-scoped queries.
25
+
26
+ The corresponding columns are also added to the `mastra_experiments` and `mastra_experiment_results` table schemas. Existing rows backfill to `null`, matching the rest of the dataset-tenancy surface.
27
+
28
+ This release also clarifies the `targetType` contract via JSDoc:
29
+ - `CreateDatasetInput.targetType` remains optional. Datasets without a `TargetType` are **not experiment-eligible** — the experiment runner requires a non-null `CreateExperimentInput.targetType` to resolve an executor.
30
+ - `Experiment.targetType` / `CreateExperimentInput.targetType` stay required. An experiment by definition replays inputs against a specific target.
31
+
32
+ No behavior change for existing OSS-created experiments; the new fields are additive and optional.
33
+
34
+ Example:
35
+
36
+ ```ts
37
+ // Create an experiment scoped to a tenancy bucket. When the parent dataset
38
+ // already carries `organizationId` / `projectId`, `runExperiment` hydrates
39
+ // these fields automatically from the dataset record.
40
+ const experiment = await storage.createExperiment({
41
+ name: 'qa-regression',
42
+ datasetId: 'ds_123',
43
+ datasetVersion: 1,
44
+ targetType: 'agent',
45
+ targetId: 'agent_qa',
46
+ totalItems: 10,
47
+ organizationId: 'org_123',
48
+ projectId: 'proj_123',
49
+ });
50
+
51
+ // List experiments within a tenancy bucket.
52
+ const experiments = await storage.listExperiments({
53
+ pagination: { page: 0, perPage: 20 },
54
+ filters: { organizationId: 'org_123', projectId: 'proj_123' },
55
+ });
56
+
57
+ // List per-item results within the same bucket.
58
+ const results = await storage.listExperimentResults({
59
+ experimentId: experiment.id,
60
+ pagination: { page: 0, perPage: 50 },
61
+ filters: { organizationId: 'org_123', projectId: 'proj_123' },
62
+ });
63
+ ```
64
+
65
+ - Persist and filter dataset tenancy + candidate identity in storage adapters. ([#18314](https://github.com/mastra-ai/mastra/pull/18314))
66
+
67
+ `createDataset` now persists `organizationId`, `projectId`, `candidateKey`, and `candidateId`. `listDatasets` and `listItems` accept matching tenancy filters. Dataset items inherit `organizationId` / `projectId` from their parent dataset on insert, update, delete, and batch insert/delete — items are never settable per call (item tenancy follows dataset tenancy).
68
+
69
+ All new columns are nullable and added retroactively via each adapter's existing column-migration path; no breaking DDL. Existing rows continue to read and write fine; new writes can choose to stamp tenancy.
70
+
71
+ ```ts
72
+ await storage.createDataset({
73
+ name: 'candidates/missing-tool-call/incident-123',
74
+ organizationId: 'org_abc',
75
+ projectId: 'project_xyz',
76
+ candidateKey: 'missing-tool-call',
77
+ candidateId: 'incident-123',
78
+ });
79
+
80
+ await storage.listDatasets({
81
+ pagination: { page: 0, perPage: 20 },
82
+ filters: { organizationId: 'org_abc', projectId: 'project_xyz' },
83
+ });
84
+ ```
85
+
86
+ - Fixed: `mastra build` output no longer hangs on the first storage-touching request when an app uses `LibSQLStore`, `PostgresStore`, or `MySQLStore` with observational memory. `mastra dev` was unaffected; only the bundled `mastra start` output deadlocked. No code changes or `bundler.externals` workaround required on the app side after upgrading. ([#18302](https://github.com/mastra-ai/mastra/pull/18302))
87
+
88
+ - Updated dependencies [[`5bd72d2`](https://github.com/mastra-ai/mastra/commit/5bd72d255f45b5ea8ab342643bd463814a980a24), [`1cc9ee1`](https://github.com/mastra-ai/mastra/commit/1cc9ee1ba51db53020a735626d33017a60b4b5b3), [`417baae`](https://github.com/mastra-ai/mastra/commit/417baae40b995db5819c845036947f0c27dc1c00), [`65f255a`](https://github.com/mastra-ai/mastra/commit/65f255a38667beb6ceeadabfa9eb5059bfec8298), [`74955f9`](https://github.com/mastra-ai/mastra/commit/74955f9120cde8b1d8ce4399232b4033236be858), [`30ebaf0`](https://github.com/mastra-ai/mastra/commit/30ebaf07bed5f4d30f2f257836c15d1bf7e40aae), [`5704634`](https://github.com/mastra-ai/mastra/commit/5704634b22133167dea337a942a34f57aaa3fa14), [`5c4e9a4`](https://github.com/mastra-ai/mastra/commit/5c4e9a4cfb2216bb3ea7f8988ad3727f3b92bb3a), [`4a88c6e`](https://github.com/mastra-ai/mastra/commit/4a88c6e2bdce316f8d7551b4ec3449b0b06fc71c), [`417baae`](https://github.com/mastra-ai/mastra/commit/417baae40b995db5819c845036947f0c27dc1c00), [`74955f9`](https://github.com/mastra-ai/mastra/commit/74955f9120cde8b1d8ce4399232b4033236be858), [`74955f9`](https://github.com/mastra-ai/mastra/commit/74955f9120cde8b1d8ce4399232b4033236be858), [`25961e3`](https://github.com/mastra-ai/mastra/commit/25961e3260ff3b1464637af8fcdb36210551c39f), [`6a1428a`](https://github.com/mastra-ai/mastra/commit/6a1428a23133fc070fc6c1caa08d28f3ba4fe5ff), [`87a17ef`](https://github.com/mastra-ai/mastra/commit/87a17efbd725aca6639febdc5e69e2abb3048689), [`e11ff30`](https://github.com/mastra-ai/mastra/commit/e11ff301408bf1731dca2fb7fbfcd8c819500a35), [`7794d71`](https://github.com/mastra-ai/mastra/commit/7794d71872c68733a30e028dfb7b1705daf6c5d2), [`9d2c946`](https://github.com/mastra-ai/mastra/commit/9d2c946d0859e90ae4bcec5beeb1da7398d2ad1e), [`c0eda2b`](https://github.com/mastra-ai/mastra/commit/c0eda2bcd91a228427314b12c91d8b147f3a739f), [`7b29f33`](https://github.com/mastra-ai/mastra/commit/7b29f332a357a83e555f29e718e5f2fab9979943), [`c0eda2b`](https://github.com/mastra-ai/mastra/commit/c0eda2bcd91a228427314b12c91d8b147f3a739f), [`b13925b`](https://github.com/mastra-ai/mastra/commit/b13925bfa91aa8700f56fa54a9ce707ee7e4ba62), [`f1ec385`](https://github.com/mastra-ai/mastra/commit/f1ec385386f62b1a0847ec5353ae2bb169d1c3d9), [`e14986f`](https://github.com/mastra-ai/mastra/commit/e14986f6e5478d6384d04ff9a7f9a79a46a8b529), [`24912b1`](https://github.com/mastra-ai/mastra/commit/24912b1f855d29ec36af4ef4bde1f7417e20cdf5), [`bf94ec6`](https://github.com/mastra-ai/mastra/commit/bf94ec68192d9f16e46ef7e5ac36370aeeddf35d), [`a29f371`](https://github.com/mastra-ai/mastra/commit/a29f371aef629ac8562661524a497127e93b5131), [`7686216`](https://github.com/mastra-ai/mastra/commit/7686216f37e74568feddec17cef3c3d24e10e60a), [`74955f9`](https://github.com/mastra-ai/mastra/commit/74955f9120cde8b1d8ce4399232b4033236be858), [`073f910`](https://github.com/mastra-ai/mastra/commit/073f910481e7d94b95ba3830f96531774ae95d33), [`0be490f`](https://github.com/mastra-ai/mastra/commit/0be490fabb538c5a7de796ea0aff7d04a0bea1f3), [`0be490f`](https://github.com/mastra-ai/mastra/commit/0be490fabb538c5a7de796ea0aff7d04a0bea1f3), [`ebbe1d3`](https://github.com/mastra-ai/mastra/commit/ebbe1d31a965a3adb0e728758f326b8122b4b55f), [`974f614`](https://github.com/mastra-ai/mastra/commit/974f614e083bd68278536f94453f7b320b86a3c7), [`3818814`](https://github.com/mastra-ai/mastra/commit/38188149ce454c4403fe9fcbdf73b735c68d36be), [`975c59a`](https://github.com/mastra-ai/mastra/commit/975c59ae363ee275fc55062392e1ffd2cbccbd53), [`1f97ce5`](https://github.com/mastra-ai/mastra/commit/1f97ce5695463bebb4eaacf501da6fb403e20885), [`74955f9`](https://github.com/mastra-ai/mastra/commit/74955f9120cde8b1d8ce4399232b4033236be858), [`7f51548`](https://github.com/mastra-ai/mastra/commit/7f515481213780be7047cef00640b9d35f3d545c), [`64f58c0`](https://github.com/mastra-ai/mastra/commit/64f58c04e78b40137497d47f781e897e416f22a5), [`74955f9`](https://github.com/mastra-ai/mastra/commit/74955f9120cde8b1d8ce4399232b4033236be858), [`ebbe1d3`](https://github.com/mastra-ai/mastra/commit/ebbe1d31a965a3adb0e728758f326b8122b4b55f), [`d95f394`](https://github.com/mastra-ai/mastra/commit/d95f394fd24c8411886930d727679c4d5252aa26), [`417baae`](https://github.com/mastra-ai/mastra/commit/417baae40b995db5819c845036947f0c27dc1c00), [`8e25a78`](https://github.com/mastra-ai/mastra/commit/8e25a78e0597575f0b0729bae8c5e190c84869b5), [`417baae`](https://github.com/mastra-ai/mastra/commit/417baae40b995db5819c845036947f0c27dc1c00), [`f3f0c9d`](https://github.com/mastra-ai/mastra/commit/f3f0c9d7c878db5a13177871ce3523a14f14b311), [`a5b22d3`](https://github.com/mastra-ai/mastra/commit/a5b22d314d62a68d801886a8d3d0eb6c089473db), [`31be1cf`](https://github.com/mastra-ai/mastra/commit/31be1cf5f2a7b5eef12f6123a40653b4d8115c16), [`417baae`](https://github.com/mastra-ai/mastra/commit/417baae40b995db5819c845036947f0c27dc1c00), [`74955f9`](https://github.com/mastra-ai/mastra/commit/74955f9120cde8b1d8ce4399232b4033236be858), [`74955f9`](https://github.com/mastra-ai/mastra/commit/74955f9120cde8b1d8ce4399232b4033236be858)]:
89
+ - @mastra/core@1.46.0
90
+
3
91
  ## 0.3.0-alpha.1
4
92
 
5
93
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -296,6 +296,16 @@ var StoreOperationsMySQL = class extends storage.StoreOperations {
296
296
  const pkColumns = tableConfig.compositePrimaryKey.map((col) => quoteIdentifier(col, "primary key column")).join(", ");
297
297
  extraConstraints.push(`PRIMARY KEY (${pkColumns})`);
298
298
  }
299
+ if (tableName === storage.TABLE_WORKFLOW_SNAPSHOT) {
300
+ extraConstraints.push(
301
+ `PRIMARY KEY (${quoteIdentifier("workflow_name", "column name")}, ${quoteIdentifier("run_id", "column name")})`
302
+ );
303
+ }
304
+ if (tableName === storage.TABLE_SPANS) {
305
+ extraConstraints.push(
306
+ `PRIMARY KEY (${quoteIdentifier("traceId", "column name")}, ${quoteIdentifier("spanId", "column name")})`
307
+ );
308
+ }
299
309
  return `CREATE TABLE IF NOT EXISTS ${tableIdent} (${[...columns, ...extraConstraints].filter(Boolean).join(", ")}) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`;
300
310
  }
301
311
  isKeyColumn(tableName, columnName) {
@@ -6888,7 +6898,8 @@ var ObservabilityMySQL = class _ObservabilityMySQL extends storage.Observability
6888
6898
  statements.push(
6889
6899
  generateTableSQL({
6890
6900
  tableName: storage.TABLE_SPANS,
6891
- schema: storage.TABLE_SCHEMAS[storage.TABLE_SPANS]
6901
+ schema: storage.TABLE_SCHEMAS[storage.TABLE_SPANS],
6902
+ compositePrimaryKey: ["traceId", "spanId"]
6892
6903
  })
6893
6904
  );
6894
6905
  for (const idx of _ObservabilityMySQL.getDefaultIndexDefs()) {
@@ -9874,7 +9885,13 @@ var WorkflowsMySQL = class _WorkflowsMySQL extends storage.WorkflowsStorage {
9874
9885
  * Exports DDL statements for all managed tables.
9875
9886
  */
9876
9887
  static getExportDDL() {
9877
- return [generateTableSQL({ tableName: storage.TABLE_WORKFLOW_SNAPSHOT, schema: storage.TABLE_SCHEMAS[storage.TABLE_WORKFLOW_SNAPSHOT] })];
9888
+ return [
9889
+ generateTableSQL({
9890
+ tableName: storage.TABLE_WORKFLOW_SNAPSHOT,
9891
+ schema: storage.TABLE_SCHEMAS[storage.TABLE_WORKFLOW_SNAPSHOT],
9892
+ compositePrimaryKey: ["workflow_name", "run_id"]
9893
+ })
9894
+ ];
9878
9895
  }
9879
9896
  constructor({
9880
9897
  operations,
@@ -10052,6 +10069,17 @@ var WorkflowsMySQL = class _WorkflowsMySQL extends storage.WorkflowsStorage {
10052
10069
  const updatedAtValue = updatedAt ?? now;
10053
10070
  try {
10054
10071
  const tableName = formatTableName(storage.TABLE_WORKFLOW_SNAPSHOT);
10072
+ const [updateResult] = await this.pool.execute(
10073
+ `UPDATE ${tableName}
10074
+ SET ${quoteIdentifier("resourceId", "column name")} = ?,
10075
+ ${quoteIdentifier("snapshot", "column name")} = ?,
10076
+ ${quoteIdentifier("updatedAt", "column name")} = ?
10077
+ WHERE ${quoteIdentifier("workflow_name", "column name")} = ? AND ${quoteIdentifier("run_id", "column name")} = ?`,
10078
+ [resourceId ?? null, JSON.stringify(snapshot), transformToSqlValue(updatedAtValue), workflowName, runId]
10079
+ );
10080
+ if (updateResult.affectedRows > 0) {
10081
+ return;
10082
+ }
10055
10083
  await this.pool.execute(
10056
10084
  `INSERT INTO ${tableName} (${quoteIdentifier("workflow_name", "column name")}, ${quoteIdentifier("run_id", "column name")}, ${quoteIdentifier("resourceId", "column name")}, ${quoteIdentifier("snapshot", "column name")}, ${quoteIdentifier("createdAt", "column name")}, ${quoteIdentifier("updatedAt", "column name")})
10057
10085
  VALUES (?, ?, ?, ?, ?, ?)