@mastra/mysql 0.2.0 → 0.3.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
@@ -1,5 +1,5 @@
1
1
  import { MastraError, ErrorCategory, ErrorDomain } from '@mastra/core/error';
2
- import { StoreOperations, TABLE_CONFIGS, TABLE_WORKFLOW_SNAPSHOT, TABLE_SPANS, AgentsStorage, TABLE_AGENTS, TABLE_AGENT_VERSIONS, AGENTS_SCHEMA, AGENT_VERSIONS_SCHEMA, createStorageErrorId, normalizePerPage, calculatePagination, BlobStore, SKILL_BLOBS_SCHEMA, TABLE_SKILL_BLOBS, DatasetsStorage, TABLE_DATASETS, TABLE_DATASET_ITEMS, TABLE_DATASET_VERSIONS, DATASETS_SCHEMA, DATASET_ITEMS_SCHEMA, DATASET_VERSIONS_SCHEMA, ExperimentsStorage, TABLE_EXPERIMENTS, TABLE_EXPERIMENT_RESULTS, EXPERIMENTS_SCHEMA, EXPERIMENT_RESULTS_SCHEMA, MCPClientsStorage, TABLE_MCP_CLIENTS, TABLE_MCP_CLIENT_VERSIONS, MCP_CLIENTS_SCHEMA, MCP_CLIENT_VERSIONS_SCHEMA, MCPServersStorage, TABLE_MCP_SERVERS, TABLE_MCP_SERVER_VERSIONS, MCP_SERVERS_SCHEMA, MCP_SERVER_VERSIONS_SCHEMA, MemoryStorage, TABLE_THREADS, TABLE_MESSAGES, TABLE_RESOURCES, TABLE_SCHEMAS, ObservabilityStorage, SPAN_SCHEMA, listTracesArgsSchema, TraceStatus, toTraceSpans, PromptBlocksStorage, TABLE_PROMPT_BLOCKS, TABLE_PROMPT_BLOCK_VERSIONS, PROMPT_BLOCKS_SCHEMA, PROMPT_BLOCK_VERSIONS_SCHEMA, ScorerDefinitionsStorage, TABLE_SCORER_DEFINITIONS, TABLE_SCORER_DEFINITION_VERSIONS, SCORER_DEFINITIONS_SCHEMA, SCORER_DEFINITION_VERSIONS_SCHEMA, ScoresStorage, TABLE_SCORERS, SCORERS_SCHEMA, SkillsStorage, TABLE_SKILLS, TABLE_SKILL_VERSIONS, SKILLS_SCHEMA, SKILL_VERSIONS_SCHEMA, WorkflowsStorage, WorkspacesStorage, TABLE_WORKSPACES, TABLE_WORKSPACE_VERSIONS, WORKSPACES_SCHEMA, WORKSPACE_VERSIONS_SCHEMA, MastraCompositeStore, TABLE_FAVORITES, BackgroundTasksStorage, TABLE_BACKGROUND_TASKS, ChannelsStorage, TABLE_CHANNEL_INSTALLATIONS, TABLE_CHANNEL_CONFIG, FavoritesStorage, FAVORITES_SCHEMA, SchedulesStorage, TABLE_SCHEDULES, TABLE_SCHEDULE_TRIGGERS, ToolProviderConnectionsStorage, TABLE_TOOL_PROVIDER_CONNECTIONS, TOOL_PROVIDER_CONNECTIONS_SCHEMA } from '@mastra/core/storage';
2
+ import { StoreOperations, TABLE_CONFIGS, TABLE_WORKFLOW_SNAPSHOT, TABLE_SPANS, AgentsStorage, TABLE_AGENTS, TABLE_AGENT_VERSIONS, AGENTS_SCHEMA, AGENT_VERSIONS_SCHEMA, createStorageErrorId, normalizePerPage, calculatePagination, BlobStore, SKILL_BLOBS_SCHEMA, TABLE_SKILL_BLOBS, DatasetsStorage, TABLE_DATASETS, TABLE_DATASET_ITEMS, TABLE_DATASET_VERSIONS, DATASETS_SCHEMA, DATASET_ITEMS_SCHEMA, DATASET_VERSIONS_SCHEMA, ExperimentsStorage, TABLE_EXPERIMENTS, TABLE_EXPERIMENT_RESULTS, EXPERIMENTS_SCHEMA, EXPERIMENT_RESULTS_SCHEMA, MCPClientsStorage, TABLE_MCP_CLIENTS, TABLE_MCP_CLIENT_VERSIONS, MCP_CLIENTS_SCHEMA, MCP_CLIENT_VERSIONS_SCHEMA, MCPServersStorage, TABLE_MCP_SERVERS, TABLE_MCP_SERVER_VERSIONS, MCP_SERVERS_SCHEMA, MCP_SERVER_VERSIONS_SCHEMA, MemoryStorage, TABLE_THREADS, TABLE_MESSAGES, TABLE_RESOURCES, TABLE_SCHEMAS, OBSERVATIONAL_MEMORY_TABLE_SCHEMA, ObservabilityStorage, SPAN_SCHEMA, listTracesArgsSchema, TraceStatus, toTraceSpans, PromptBlocksStorage, TABLE_PROMPT_BLOCKS, TABLE_PROMPT_BLOCK_VERSIONS, PROMPT_BLOCKS_SCHEMA, PROMPT_BLOCK_VERSIONS_SCHEMA, ScorerDefinitionsStorage, TABLE_SCORER_DEFINITIONS, TABLE_SCORER_DEFINITION_VERSIONS, SCORER_DEFINITIONS_SCHEMA, SCORER_DEFINITION_VERSIONS_SCHEMA, ScoresStorage, TABLE_SCORERS, SCORERS_SCHEMA, SkillsStorage, TABLE_SKILLS, TABLE_SKILL_VERSIONS, SKILLS_SCHEMA, SKILL_VERSIONS_SCHEMA, WorkflowsStorage, WorkspacesStorage, TABLE_WORKSPACES, TABLE_WORKSPACE_VERSIONS, WORKSPACES_SCHEMA, WORKSPACE_VERSIONS_SCHEMA, MastraCompositeStore, TABLE_FAVORITES, BackgroundTasksStorage, TABLE_BACKGROUND_TASKS, ChannelsStorage, TABLE_CHANNEL_INSTALLATIONS, TABLE_CHANNEL_CONFIG, FavoritesStorage, FAVORITES_SCHEMA, SchedulesStorage, TABLE_SCHEDULES, TABLE_SCHEDULE_TRIGGERS, ToolProviderConnectionsStorage, TABLE_TOOL_PROVIDER_CONNECTIONS, TOOL_PROVIDER_CONNECTIONS_SCHEMA } from '@mastra/core/storage';
3
3
  import { createPool } from 'mysql2/promise';
4
4
  import { parseSqlIdentifier } from '@mastra/core/utils';
5
5
  import { randomUUID } from 'crypto';
@@ -2056,6 +2056,21 @@ var DatasetsMySQL = class _DatasetsMySQL extends DatasetsStorage {
2056
2056
  #indexes;
2057
2057
  /** Tables managed by this domain */
2058
2058
  static MANAGED_TABLES = [TABLE_DATASETS, TABLE_DATASET_ITEMS, TABLE_DATASET_VERSIONS];
2059
+ /**
2060
+ * Item-level tool mocks are not persisted by the MySQL adapter. Reject writes
2061
+ * that carry them so the feature fails loudly here instead of silently dropping
2062
+ * the mocks and then running tools live during experiments.
2063
+ */
2064
+ #rejectToolMocks(toolMocks) {
2065
+ if (Array.isArray(toolMocks) && toolMocks.length > 0) {
2066
+ throw new MastraError({
2067
+ id: "MYSQL_DATASET_TOOL_MOCKS_UNSUPPORTED",
2068
+ domain: ErrorDomain.STORAGE,
2069
+ category: ErrorCategory.USER,
2070
+ text: "Tool mocks are not supported on the MySQL storage adapter. Use a supported adapter (LibSQL, PostgreSQL, MongoDB, or Spanner) to persist dataset item tool mocks."
2071
+ });
2072
+ }
2073
+ }
2059
2074
  /**
2060
2075
  * Returns default index definitions for the datasets domain tables.
2061
2076
  * Currently no default indexes are defined for datasets.
@@ -2115,6 +2130,16 @@ var DatasetsMySQL = class _DatasetsMySQL extends DatasetsStorage {
2115
2130
  await this.operations.createTable({ tableName: TABLE_DATASETS, schema: DATASETS_SCHEMA });
2116
2131
  await this.operations.createTable({ tableName: TABLE_DATASET_ITEMS, schema: DATASET_ITEMS_SCHEMA });
2117
2132
  await this.operations.createTable({ tableName: TABLE_DATASET_VERSIONS, schema: DATASET_VERSIONS_SCHEMA });
2133
+ await this.operations.alterTable({
2134
+ tableName: TABLE_DATASETS,
2135
+ schema: DATASETS_SCHEMA,
2136
+ ifNotExists: ["organizationId", "projectId", "candidateKey", "candidateId"]
2137
+ });
2138
+ await this.operations.alterTable({
2139
+ tableName: TABLE_DATASET_ITEMS,
2140
+ schema: DATASET_ITEMS_SCHEMA,
2141
+ ifNotExists: ["organizationId", "projectId"]
2142
+ });
2118
2143
  await this.createDefaultIndexes();
2119
2144
  await this.createCustomIndexes();
2120
2145
  }
@@ -2133,6 +2158,10 @@ var DatasetsMySQL = class _DatasetsMySQL extends DatasetsStorage {
2133
2158
  inputSchema: parseJSON(row.inputSchema),
2134
2159
  groundTruthSchema: parseJSON(row.groundTruthSchema),
2135
2160
  version: row.version,
2161
+ organizationId: row.organizationId ?? null,
2162
+ projectId: row.projectId ?? null,
2163
+ candidateKey: row.candidateKey ?? null,
2164
+ candidateId: row.candidateId ?? null,
2136
2165
  createdAt: parseDateTime(row.createdAt) ?? /* @__PURE__ */ new Date(),
2137
2166
  updatedAt: parseDateTime(row.updatedAt) ?? /* @__PURE__ */ new Date()
2138
2167
  };
@@ -2142,6 +2171,8 @@ var DatasetsMySQL = class _DatasetsMySQL extends DatasetsStorage {
2142
2171
  id: row.id,
2143
2172
  datasetId: row.datasetId,
2144
2173
  datasetVersion: row.datasetVersion,
2174
+ organizationId: row.organizationId ?? null,
2175
+ projectId: row.projectId ?? null,
2145
2176
  input: parseJSON(row.input),
2146
2177
  groundTruth: row.groundTruth ? parseJSON(row.groundTruth) : void 0,
2147
2178
  metadata: row.metadata ? parseJSON(row.metadata) : void 0,
@@ -2154,6 +2185,8 @@ var DatasetsMySQL = class _DatasetsMySQL extends DatasetsStorage {
2154
2185
  id: row.id,
2155
2186
  datasetId: row.datasetId,
2156
2187
  datasetVersion: row.datasetVersion,
2188
+ organizationId: row.organizationId ?? null,
2189
+ projectId: row.projectId ?? null,
2157
2190
  validTo: row.validTo,
2158
2191
  isDeleted: Boolean(row.isDeleted),
2159
2192
  input: parseJSON(row.input),
@@ -2186,6 +2219,10 @@ var DatasetsMySQL = class _DatasetsMySQL extends DatasetsStorage {
2186
2219
  inputSchema: jsonArg(input.inputSchema),
2187
2220
  groundTruthSchema: jsonArg(input.groundTruthSchema),
2188
2221
  version: 0,
2222
+ organizationId: input.organizationId ?? null,
2223
+ projectId: input.projectId ?? null,
2224
+ candidateKey: input.candidateKey ?? null,
2225
+ candidateId: input.candidateId ?? null,
2189
2226
  createdAt: now,
2190
2227
  updatedAt: now
2191
2228
  }
@@ -2198,6 +2235,10 @@ var DatasetsMySQL = class _DatasetsMySQL extends DatasetsStorage {
2198
2235
  inputSchema: input.inputSchema ?? void 0,
2199
2236
  groundTruthSchema: input.groundTruthSchema ?? void 0,
2200
2237
  version: 0,
2238
+ organizationId: input.organizationId ?? null,
2239
+ projectId: input.projectId ?? null,
2240
+ candidateKey: input.candidateKey ?? null,
2241
+ candidateId: input.candidateId ?? null,
2201
2242
  createdAt: now,
2202
2243
  updatedAt: now
2203
2244
  };
@@ -2320,7 +2361,28 @@ var DatasetsMySQL = class _DatasetsMySQL extends DatasetsStorage {
2320
2361
  async listDatasets(args) {
2321
2362
  try {
2322
2363
  const { page, perPage: perPageInput } = args.pagination;
2323
- const whereClause = { sql: "", args: [] };
2364
+ const filterParts = [];
2365
+ const filterArgs = [];
2366
+ if (args.filters?.organizationId !== void 0) {
2367
+ filterParts.push(`${quoteIdentifier("organizationId", "column name")} = ?`);
2368
+ filterArgs.push(args.filters.organizationId);
2369
+ }
2370
+ if (args.filters?.projectId !== void 0) {
2371
+ filterParts.push(`${quoteIdentifier("projectId", "column name")} = ?`);
2372
+ filterArgs.push(args.filters.projectId);
2373
+ }
2374
+ if (args.filters?.candidateKey !== void 0) {
2375
+ filterParts.push(`${quoteIdentifier("candidateKey", "column name")} = ?`);
2376
+ filterArgs.push(args.filters.candidateKey);
2377
+ }
2378
+ if (args.filters?.candidateId !== void 0) {
2379
+ filterParts.push(`${quoteIdentifier("candidateId", "column name")} = ?`);
2380
+ filterArgs.push(args.filters.candidateId);
2381
+ }
2382
+ const whereClause = {
2383
+ sql: filterParts.length > 0 ? `WHERE ${filterParts.join(" AND ")}` : "",
2384
+ args: filterArgs
2385
+ };
2324
2386
  const total = await this.operations.loadTotalCount({ tableName: TABLE_DATASETS, whereClause });
2325
2387
  if (total === 0) {
2326
2388
  return {
@@ -2360,6 +2422,7 @@ var DatasetsMySQL = class _DatasetsMySQL extends DatasetsStorage {
2360
2422
  }
2361
2423
  // --- SCD-2 item mutations ---
2362
2424
  async _doAddItem(args) {
2425
+ this.#rejectToolMocks(args.toolMocks);
2363
2426
  const connection = await this.pool.getConnection();
2364
2427
  try {
2365
2428
  await connection.beginTransaction();
@@ -2372,17 +2435,22 @@ var DatasetsMySQL = class _DatasetsMySQL extends DatasetsStorage {
2372
2435
  await connection.execute(`UPDATE ${tableDatasetsName} SET \`version\` = \`version\` + 1 WHERE id = ?`, [
2373
2436
  args.datasetId
2374
2437
  ]);
2375
- const [versionRows] = await connection.execute(
2376
- `SELECT \`version\` FROM ${tableDatasetsName} WHERE id = ?`,
2438
+ const [datasetRows] = await connection.execute(
2439
+ `SELECT \`version\`, \`organizationId\`, \`projectId\` FROM ${tableDatasetsName} WHERE id = ?`,
2377
2440
  [args.datasetId]
2378
2441
  );
2379
- const newVersion = versionRows[0]?.version;
2442
+ const parentRow = datasetRows[0];
2443
+ const newVersion = parentRow?.version;
2444
+ const parentOrganizationId = parentRow?.organizationId ?? null;
2445
+ const parentProjectId = parentRow?.projectId ?? null;
2380
2446
  await connection.execute(
2381
- `INSERT INTO ${tableItemsName} (\`id\`, \`datasetId\`, \`datasetVersion\`, \`validTo\`, \`isDeleted\`, \`input\`, \`groundTruth\`, \`metadata\`, \`createdAt\`, \`updatedAt\`) VALUES (?, ?, ?, NULL, 0, ?, ?, ?, ?, ?)`,
2447
+ `INSERT INTO ${tableItemsName} (\`id\`, \`datasetId\`, \`datasetVersion\`, \`organizationId\`, \`projectId\`, \`validTo\`, \`isDeleted\`, \`input\`, \`groundTruth\`, \`metadata\`, \`createdAt\`, \`updatedAt\`) VALUES (?, ?, ?, ?, ?, NULL, 0, ?, ?, ?, ?, ?)`,
2382
2448
  [
2383
2449
  id,
2384
2450
  args.datasetId,
2385
2451
  newVersion,
2452
+ parentOrganizationId,
2453
+ parentProjectId,
2386
2454
  jsonArg(args.input),
2387
2455
  jsonArg(args.groundTruth),
2388
2456
  jsonArg(args.metadata),
@@ -2399,6 +2467,8 @@ var DatasetsMySQL = class _DatasetsMySQL extends DatasetsStorage {
2399
2467
  id,
2400
2468
  datasetId: args.datasetId,
2401
2469
  datasetVersion: newVersion,
2470
+ organizationId: parentOrganizationId,
2471
+ projectId: parentProjectId,
2402
2472
  input: args.input,
2403
2473
  groundTruth: args.groundTruth,
2404
2474
  metadata: args.metadata,
@@ -2421,6 +2491,7 @@ var DatasetsMySQL = class _DatasetsMySQL extends DatasetsStorage {
2421
2491
  }
2422
2492
  }
2423
2493
  async _doUpdateItem(args) {
2494
+ this.#rejectToolMocks(args.toolMocks);
2424
2495
  const existing = await this.getItemById({ id: args.id });
2425
2496
  if (!existing) {
2426
2497
  throw new MastraError({
@@ -2452,21 +2523,26 @@ var DatasetsMySQL = class _DatasetsMySQL extends DatasetsStorage {
2452
2523
  await connection.execute(`UPDATE ${tableDatasetsName} SET \`version\` = \`version\` + 1 WHERE id = ?`, [
2453
2524
  args.datasetId
2454
2525
  ]);
2455
- const [versionRows] = await connection.execute(
2456
- `SELECT \`version\` FROM ${tableDatasetsName} WHERE id = ?`,
2526
+ const [datasetRows] = await connection.execute(
2527
+ `SELECT \`version\`, \`organizationId\`, \`projectId\` FROM ${tableDatasetsName} WHERE id = ?`,
2457
2528
  [args.datasetId]
2458
2529
  );
2459
- const newVersion = versionRows[0]?.version;
2530
+ const parentRow = datasetRows[0];
2531
+ const newVersion = parentRow?.version;
2532
+ const parentOrganizationId = parentRow?.organizationId ?? null;
2533
+ const parentProjectId = parentRow?.projectId ?? null;
2460
2534
  await connection.execute(
2461
2535
  `UPDATE ${tableItemsName} SET \`validTo\` = ? WHERE \`id\` = ? AND \`validTo\` IS NULL AND \`isDeleted\` = 0`,
2462
2536
  [newVersion, args.id]
2463
2537
  );
2464
2538
  await connection.execute(
2465
- `INSERT INTO ${tableItemsName} (\`id\`, \`datasetId\`, \`datasetVersion\`, \`validTo\`, \`isDeleted\`, \`input\`, \`groundTruth\`, \`metadata\`, \`createdAt\`, \`updatedAt\`) VALUES (?, ?, ?, NULL, 0, ?, ?, ?, ?, ?)`,
2539
+ `INSERT INTO ${tableItemsName} (\`id\`, \`datasetId\`, \`datasetVersion\`, \`organizationId\`, \`projectId\`, \`validTo\`, \`isDeleted\`, \`input\`, \`groundTruth\`, \`metadata\`, \`createdAt\`, \`updatedAt\`) VALUES (?, ?, ?, ?, ?, NULL, 0, ?, ?, ?, ?, ?)`,
2466
2540
  [
2467
2541
  args.id,
2468
2542
  args.datasetId,
2469
2543
  newVersion,
2544
+ parentOrganizationId,
2545
+ parentProjectId,
2470
2546
  jsonArg(mergedInput),
2471
2547
  jsonArg(mergedGroundTruth),
2472
2548
  jsonArg(mergedMetadata),
@@ -2482,6 +2558,8 @@ var DatasetsMySQL = class _DatasetsMySQL extends DatasetsStorage {
2482
2558
  return {
2483
2559
  ...existing,
2484
2560
  datasetVersion: newVersion,
2561
+ organizationId: parentOrganizationId,
2562
+ projectId: parentProjectId,
2485
2563
  input: mergedInput,
2486
2564
  groundTruth: mergedGroundTruth,
2487
2565
  metadata: mergedMetadata,
@@ -2524,21 +2602,26 @@ var DatasetsMySQL = class _DatasetsMySQL extends DatasetsStorage {
2524
2602
  await connection.execute(`UPDATE ${tableDatasetsName} SET \`version\` = \`version\` + 1 WHERE id = ?`, [
2525
2603
  datasetId
2526
2604
  ]);
2527
- const [versionRows] = await connection.execute(
2528
- `SELECT \`version\` FROM ${tableDatasetsName} WHERE id = ?`,
2605
+ const [datasetRows] = await connection.execute(
2606
+ `SELECT \`version\`, \`organizationId\`, \`projectId\` FROM ${tableDatasetsName} WHERE id = ?`,
2529
2607
  [datasetId]
2530
2608
  );
2531
- const newVersion = versionRows[0]?.version;
2609
+ const parentRow = datasetRows[0];
2610
+ const newVersion = parentRow?.version;
2611
+ const parentOrganizationId = parentRow?.organizationId ?? null;
2612
+ const parentProjectId = parentRow?.projectId ?? null;
2532
2613
  await connection.execute(
2533
2614
  `UPDATE ${tableItemsName} SET \`validTo\` = ? WHERE \`id\` = ? AND \`validTo\` IS NULL AND \`isDeleted\` = 0`,
2534
2615
  [newVersion, id]
2535
2616
  );
2536
2617
  await connection.execute(
2537
- `INSERT INTO ${tableItemsName} (\`id\`, \`datasetId\`, \`datasetVersion\`, \`validTo\`, \`isDeleted\`, \`input\`, \`groundTruth\`, \`metadata\`, \`createdAt\`, \`updatedAt\`) VALUES (?, ?, ?, NULL, 1, ?, ?, ?, ?, ?)`,
2618
+ `INSERT INTO ${tableItemsName} (\`id\`, \`datasetId\`, \`datasetVersion\`, \`organizationId\`, \`projectId\`, \`validTo\`, \`isDeleted\`, \`input\`, \`groundTruth\`, \`metadata\`, \`createdAt\`, \`updatedAt\`) VALUES (?, ?, ?, ?, ?, NULL, 1, ?, ?, ?, ?, ?)`,
2538
2619
  [
2539
2620
  id,
2540
2621
  datasetId,
2541
2622
  newVersion,
2623
+ parentOrganizationId,
2624
+ parentProjectId,
2542
2625
  jsonArg(existing.input),
2543
2626
  jsonArg(existing.groundTruth),
2544
2627
  jsonArg(existing.metadata),
@@ -2647,6 +2730,14 @@ var DatasetsMySQL = class _DatasetsMySQL extends DatasetsStorage {
2647
2730
  conditions.push(`\`validTo\` IS NULL`);
2648
2731
  conditions.push(`\`isDeleted\` = 0`);
2649
2732
  }
2733
+ if (args.filters?.organizationId !== void 0) {
2734
+ conditions.push(`\`organizationId\` = ?`);
2735
+ params.push(args.filters.organizationId);
2736
+ }
2737
+ if (args.filters?.projectId !== void 0) {
2738
+ conditions.push(`\`projectId\` = ?`);
2739
+ params.push(args.filters.projectId);
2740
+ }
2650
2741
  if (args.search) {
2651
2742
  conditions.push(`(LOWER(\`input\`) LIKE ? OR LOWER(COALESCE(\`groundTruth\`, '')) LIKE ?)`);
2652
2743
  const searchPattern = `%${args.search.toLowerCase()}%`;
@@ -2763,6 +2854,9 @@ var DatasetsMySQL = class _DatasetsMySQL extends DatasetsStorage {
2763
2854
  }
2764
2855
  // --- Bulk operations (SCD-2 internally) ---
2765
2856
  async _doBatchInsertItems(input) {
2857
+ for (const item of input.items) {
2858
+ this.#rejectToolMocks(item.toolMocks);
2859
+ }
2766
2860
  const dataset = await this.getDatasetById({ id: input.datasetId });
2767
2861
  if (!dataset) {
2768
2862
  throw new MastraError({
@@ -2788,16 +2882,20 @@ var DatasetsMySQL = class _DatasetsMySQL extends DatasetsStorage {
2788
2882
  [input.datasetId]
2789
2883
  );
2790
2884
  const newVersion = versionRows[0]?.version;
2885
+ const parentOrganizationId = dataset.organizationId ?? null;
2886
+ const parentProjectId = dataset.projectId ?? null;
2791
2887
  const items = [];
2792
2888
  for (const itemInput of input.items) {
2793
2889
  const id = randomUUID();
2794
2890
  items.push({ id, itemInput });
2795
2891
  await connection.execute(
2796
- `INSERT INTO ${tableItemsName} (\`id\`, \`datasetId\`, \`datasetVersion\`, \`validTo\`, \`isDeleted\`, \`input\`, \`groundTruth\`, \`metadata\`, \`createdAt\`, \`updatedAt\`) VALUES (?, ?, ?, NULL, 0, ?, ?, ?, ?, ?)`,
2892
+ `INSERT INTO ${tableItemsName} (\`id\`, \`datasetId\`, \`datasetVersion\`, \`organizationId\`, \`projectId\`, \`validTo\`, \`isDeleted\`, \`input\`, \`groundTruth\`, \`metadata\`, \`createdAt\`, \`updatedAt\`) VALUES (?, ?, ?, ?, ?, NULL, 0, ?, ?, ?, ?, ?)`,
2797
2893
  [
2798
2894
  id,
2799
2895
  input.datasetId,
2800
2896
  newVersion,
2897
+ parentOrganizationId,
2898
+ parentProjectId,
2801
2899
  jsonArg(itemInput.input),
2802
2900
  jsonArg(itemInput.groundTruth),
2803
2901
  jsonArg(itemInput.metadata),
@@ -2815,6 +2913,8 @@ var DatasetsMySQL = class _DatasetsMySQL extends DatasetsStorage {
2815
2913
  id,
2816
2914
  datasetId: input.datasetId,
2817
2915
  datasetVersion: newVersion,
2916
+ organizationId: parentOrganizationId,
2917
+ projectId: parentProjectId,
2818
2918
  input: itemInput.input,
2819
2919
  groundTruth: itemInput.groundTruth,
2820
2920
  metadata: itemInput.metadata,
@@ -2870,17 +2970,21 @@ var DatasetsMySQL = class _DatasetsMySQL extends DatasetsStorage {
2870
2970
  [input.datasetId]
2871
2971
  );
2872
2972
  const newVersion = versionRows[0]?.version;
2973
+ const parentOrganizationId = dataset.organizationId ?? null;
2974
+ const parentProjectId = dataset.projectId ?? null;
2873
2975
  for (const item of currentItems) {
2874
2976
  await connection.execute(
2875
2977
  `UPDATE ${tableItemsName} SET \`validTo\` = ? WHERE \`id\` = ? AND \`validTo\` IS NULL AND \`isDeleted\` = 0`,
2876
2978
  [newVersion, item.id]
2877
2979
  );
2878
2980
  await connection.execute(
2879
- `INSERT INTO ${tableItemsName} (\`id\`, \`datasetId\`, \`datasetVersion\`, \`validTo\`, \`isDeleted\`, \`input\`, \`groundTruth\`, \`metadata\`, \`createdAt\`, \`updatedAt\`) VALUES (?, ?, ?, NULL, 1, ?, ?, ?, ?, ?)`,
2981
+ `INSERT INTO ${tableItemsName} (\`id\`, \`datasetId\`, \`datasetVersion\`, \`organizationId\`, \`projectId\`, \`validTo\`, \`isDeleted\`, \`input\`, \`groundTruth\`, \`metadata\`, \`createdAt\`, \`updatedAt\`) VALUES (?, ?, ?, ?, ?, NULL, 1, ?, ?, ?, ?, ?)`,
2880
2982
  [
2881
2983
  item.id,
2882
2984
  input.datasetId,
2883
2985
  newVersion,
2986
+ parentOrganizationId,
2987
+ parentProjectId,
2884
2988
  jsonArg(item.input),
2885
2989
  jsonArg(item.groundTruth),
2886
2990
  jsonArg(item.metadata),
@@ -2932,10 +3036,22 @@ var ExperimentsMySQL = class _ExperimentsMySQL extends ExperimentsStorage {
2932
3036
  static MANAGED_TABLES = [TABLE_EXPERIMENTS, TABLE_EXPERIMENT_RESULTS];
2933
3037
  /**
2934
3038
  * Returns default index definitions for the experiments domain tables.
2935
- * Currently no default indexes are defined for experiments.
2936
3039
  */
2937
3040
  static getDefaultIndexDefs(_prefix = "") {
2938
- return [];
3041
+ return [
3042
+ // Tenancy: leading-tenant indexes for multi-tenant scans (parity with
3043
+ // pg/libsql/spanner/mongodb experiments adapters).
3044
+ {
3045
+ name: "idx_experiments_org_project",
3046
+ table: TABLE_EXPERIMENTS,
3047
+ columns: ["organizationId", "projectId"]
3048
+ },
3049
+ {
3050
+ name: "idx_experiment_results_org_project",
3051
+ table: TABLE_EXPERIMENT_RESULTS,
3052
+ columns: ["organizationId", "projectId"]
3053
+ }
3054
+ ];
2939
3055
  }
2940
3056
  /**
2941
3057
  * Exports DDL statements for all managed tables.
@@ -2966,10 +3082,12 @@ var ExperimentsMySQL = class _ExperimentsMySQL extends ExperimentsStorage {
2966
3082
  }
2967
3083
  /**
2968
3084
  * Creates default indexes for optimal query performance.
2969
- * Currently no default indexes are defined for experiments.
2970
3085
  */
2971
3086
  async createDefaultIndexes() {
2972
3087
  if (this.#skipDefaultIndexes) return;
3088
+ for (const indexDef of this.getDefaultIndexDefinitions()) {
3089
+ await this.operations.createIndex(indexDef);
3090
+ }
2973
3091
  }
2974
3092
  /**
2975
3093
  * Creates custom user-defined indexes for this domain's tables.
@@ -2983,6 +3101,16 @@ var ExperimentsMySQL = class _ExperimentsMySQL extends ExperimentsStorage {
2983
3101
  async init() {
2984
3102
  await this.operations.createTable({ tableName: TABLE_EXPERIMENTS, schema: EXPERIMENTS_SCHEMA });
2985
3103
  await this.operations.createTable({ tableName: TABLE_EXPERIMENT_RESULTS, schema: EXPERIMENT_RESULTS_SCHEMA });
3104
+ await this.operations.alterTable({
3105
+ tableName: TABLE_EXPERIMENTS,
3106
+ schema: EXPERIMENTS_SCHEMA,
3107
+ ifNotExists: ["organizationId", "projectId"]
3108
+ });
3109
+ await this.operations.alterTable({
3110
+ tableName: TABLE_EXPERIMENT_RESULTS,
3111
+ schema: EXPERIMENT_RESULTS_SCHEMA,
3112
+ ifNotExists: ["organizationId", "projectId"]
3113
+ });
2986
3114
  await this.createDefaultIndexes();
2987
3115
  await this.createCustomIndexes();
2988
3116
  }
@@ -2995,6 +3123,8 @@ var ExperimentsMySQL = class _ExperimentsMySQL extends ExperimentsStorage {
2995
3123
  id: row.id,
2996
3124
  datasetId: row.datasetId ?? null,
2997
3125
  datasetVersion: row.datasetVersion ?? null,
3126
+ organizationId: row.organizationId ?? null,
3127
+ projectId: row.projectId ?? null,
2998
3128
  targetType: row.targetType,
2999
3129
  targetId: row.targetId,
3000
3130
  name: row.name ?? void 0,
@@ -3017,6 +3147,8 @@ var ExperimentsMySQL = class _ExperimentsMySQL extends ExperimentsStorage {
3017
3147
  experimentId: row.experimentId,
3018
3148
  itemId: row.itemId,
3019
3149
  itemDatasetVersion: row.itemDatasetVersion ?? null,
3150
+ organizationId: row.organizationId ?? null,
3151
+ projectId: row.projectId ?? null,
3020
3152
  input: parseJSON2(row.input),
3021
3153
  output: row.output ? parseJSON2(row.output) : null,
3022
3154
  groundTruth: row.groundTruth ? parseJSON2(row.groundTruth) : null,
@@ -3040,6 +3172,8 @@ var ExperimentsMySQL = class _ExperimentsMySQL extends ExperimentsStorage {
3040
3172
  id,
3041
3173
  datasetId: input.datasetId ?? null,
3042
3174
  datasetVersion: input.datasetVersion ?? null,
3175
+ organizationId: input.organizationId ?? null,
3176
+ projectId: input.projectId ?? null,
3043
3177
  targetType: input.targetType,
3044
3178
  targetId: input.targetId,
3045
3179
  name: input.name ?? null,
@@ -3060,6 +3194,8 @@ var ExperimentsMySQL = class _ExperimentsMySQL extends ExperimentsStorage {
3060
3194
  id,
3061
3195
  datasetId: input.datasetId,
3062
3196
  datasetVersion: input.datasetVersion,
3197
+ organizationId: input.organizationId ?? null,
3198
+ projectId: input.projectId ?? null,
3063
3199
  targetType: input.targetType,
3064
3200
  targetId: input.targetId,
3065
3201
  name: input.name,
@@ -3154,6 +3290,17 @@ var ExperimentsMySQL = class _ExperimentsMySQL extends ExperimentsStorage {
3154
3290
  conditions.push(`${quoteIdentifier("datasetId", "column name")} = ?`);
3155
3291
  params.push(args.datasetId);
3156
3292
  }
3293
+ if (args.filters) {
3294
+ const { organizationId, projectId } = args.filters;
3295
+ if (organizationId !== void 0) {
3296
+ conditions.push(`${quoteIdentifier("organizationId", "column name")} = ?`);
3297
+ params.push(organizationId);
3298
+ }
3299
+ if (projectId !== void 0) {
3300
+ conditions.push(`${quoteIdentifier("projectId", "column name")} = ?`);
3301
+ params.push(projectId);
3302
+ }
3303
+ }
3157
3304
  const whereClause = {
3158
3305
  sql: conditions.length > 0 ? ` WHERE ${conditions.join(" AND ")}` : "",
3159
3306
  args: params
@@ -3239,6 +3386,14 @@ var ExperimentsMySQL = class _ExperimentsMySQL extends ExperimentsStorage {
3239
3386
  }
3240
3387
  }
3241
3388
  async addExperimentResult(input) {
3389
+ if (input.toolMockReport) {
3390
+ throw new MastraError({
3391
+ id: "MYSQL_EXPERIMENT_TOOL_MOCK_REPORT_UNSUPPORTED",
3392
+ domain: ErrorDomain.STORAGE,
3393
+ category: ErrorCategory.USER,
3394
+ text: "Tool mock reports are not supported on the MySQL storage adapter. Use a supported adapter (LibSQL, PostgreSQL, MongoDB, or Spanner) to persist experiment tool mock reports."
3395
+ });
3396
+ }
3242
3397
  try {
3243
3398
  const id = input.id ?? randomUUID();
3244
3399
  const now = /* @__PURE__ */ new Date();
@@ -3249,6 +3404,8 @@ var ExperimentsMySQL = class _ExperimentsMySQL extends ExperimentsStorage {
3249
3404
  experimentId: input.experimentId,
3250
3405
  itemId: input.itemId,
3251
3406
  itemDatasetVersion: input.itemDatasetVersion ?? null,
3407
+ organizationId: input.organizationId ?? null,
3408
+ projectId: input.projectId ?? null,
3252
3409
  input: JSON.stringify(input.input),
3253
3410
  output: input.output ? JSON.stringify(input.output) : null,
3254
3411
  groundTruth: input.groundTruth ? JSON.stringify(input.groundTruth) : null,
@@ -3267,6 +3424,8 @@ var ExperimentsMySQL = class _ExperimentsMySQL extends ExperimentsStorage {
3267
3424
  experimentId: input.experimentId,
3268
3425
  itemId: input.itemId,
3269
3426
  itemDatasetVersion: input.itemDatasetVersion,
3427
+ organizationId: input.organizationId ?? null,
3428
+ projectId: input.projectId ?? null,
3270
3429
  input: input.input,
3271
3430
  output: input.output,
3272
3431
  groundTruth: input.groundTruth,
@@ -3384,9 +3543,30 @@ var ExperimentsMySQL = class _ExperimentsMySQL extends ExperimentsStorage {
3384
3543
  async listExperimentResults(args) {
3385
3544
  try {
3386
3545
  const { page, perPage: perPageInput } = args.pagination;
3546
+ const conditions = [`${quoteIdentifier("experimentId", "column name")} = ?`];
3547
+ const params = [args.experimentId];
3548
+ if (args.traceId) {
3549
+ conditions.push(`${quoteIdentifier("traceId", "column name")} = ?`);
3550
+ params.push(args.traceId);
3551
+ }
3552
+ if (args.status) {
3553
+ conditions.push(`${quoteIdentifier("status", "column name")} = ?`);
3554
+ params.push(args.status);
3555
+ }
3556
+ if (args.filters) {
3557
+ const { organizationId, projectId } = args.filters;
3558
+ if (organizationId !== void 0) {
3559
+ conditions.push(`${quoteIdentifier("organizationId", "column name")} = ?`);
3560
+ params.push(organizationId);
3561
+ }
3562
+ if (projectId !== void 0) {
3563
+ conditions.push(`${quoteIdentifier("projectId", "column name")} = ?`);
3564
+ params.push(projectId);
3565
+ }
3566
+ }
3387
3567
  const whereClause = {
3388
- sql: ` WHERE ${quoteIdentifier("experimentId", "column name")} = ?`,
3389
- args: [args.experimentId]
3568
+ sql: ` WHERE ${conditions.join(" AND ")}`,
3569
+ args: params
3390
3570
  };
3391
3571
  const total = await this.operations.loadTotalCount({ tableName: TABLE_EXPERIMENT_RESULTS, whereClause });
3392
3572
  if (total === 0) {
@@ -4792,12 +4972,7 @@ var MemoryMySQL = class _MemoryMySQL extends MemoryStorage {
4792
4972
  await this.operations.createTable({ tableName: TABLE_THREADS, schema: TABLE_SCHEMAS[TABLE_THREADS] });
4793
4973
  await this.operations.createTable({ tableName: TABLE_MESSAGES, schema: TABLE_SCHEMAS[TABLE_MESSAGES] });
4794
4974
  await this.operations.createTable({ tableName: TABLE_RESOURCES, schema: TABLE_SCHEMAS[TABLE_RESOURCES] });
4795
- let omSchema;
4796
- try {
4797
- const { OBSERVATIONAL_MEMORY_TABLE_SCHEMA } = await import('@mastra/core/storage');
4798
- omSchema = OBSERVATIONAL_MEMORY_TABLE_SCHEMA?.[OM_TABLE];
4799
- } catch {
4800
- }
4975
+ const omSchema = OBSERVATIONAL_MEMORY_TABLE_SCHEMA?.[OM_TABLE];
4801
4976
  if (omSchema) {
4802
4977
  await this.operations.createTable({
4803
4978
  tableName: OM_TABLE,