@mastra/mongodb 1.10.0 → 1.11.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/CHANGELOG.md CHANGED
@@ -1,5 +1,89 @@
1
1
  # @mastra/mongodb
2
2
 
3
+ ## 1.11.0-alpha.1
4
+
5
+ ### Minor Changes
6
+
7
+ - Fixed new observability span writes in MongoDB so `startedAt`, `endedAt`, `createdAt`, and `updatedAt` are stored as native BSON Date objects. Existing string-typed span dates remain readable and date filters support both old string values and new Date values. ([#18366](https://github.com/mastra-ai/mastra/pull/18366))
8
+
9
+ ### Patch Changes
10
+
11
+ - 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))
12
+
13
+ `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.
14
+
15
+ 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.
16
+
17
+ This release also clarifies the `targetType` contract via JSDoc:
18
+ - `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.
19
+ - `Experiment.targetType` / `CreateExperimentInput.targetType` stay required. An experiment by definition replays inputs against a specific target.
20
+
21
+ No behavior change for existing OSS-created experiments; the new fields are additive and optional.
22
+
23
+ Example:
24
+
25
+ ```ts
26
+ // Create an experiment scoped to a tenancy bucket. When the parent dataset
27
+ // already carries `organizationId` / `projectId`, `runExperiment` hydrates
28
+ // these fields automatically from the dataset record.
29
+ const experiment = await storage.createExperiment({
30
+ name: 'qa-regression',
31
+ datasetId: 'ds_123',
32
+ datasetVersion: 1,
33
+ targetType: 'agent',
34
+ targetId: 'agent_qa',
35
+ totalItems: 10,
36
+ organizationId: 'org_123',
37
+ projectId: 'proj_123',
38
+ });
39
+
40
+ // List experiments within a tenancy bucket.
41
+ const experiments = await storage.listExperiments({
42
+ pagination: { page: 0, perPage: 20 },
43
+ filters: { organizationId: 'org_123', projectId: 'proj_123' },
44
+ });
45
+
46
+ // List per-item results within the same bucket.
47
+ const results = await storage.listExperimentResults({
48
+ experimentId: experiment.id,
49
+ pagination: { page: 0, perPage: 50 },
50
+ filters: { organizationId: 'org_123', projectId: 'proj_123' },
51
+ });
52
+ ```
53
+
54
+ - Persist and filter dataset tenancy + candidate identity in storage adapters. ([#18314](https://github.com/mastra-ai/mastra/pull/18314))
55
+
56
+ `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).
57
+
58
+ 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.
59
+
60
+ ```ts
61
+ await storage.createDataset({
62
+ name: 'candidates/missing-tool-call/incident-123',
63
+ organizationId: 'org_abc',
64
+ projectId: 'project_xyz',
65
+ candidateKey: 'missing-tool-call',
66
+ candidateId: 'incident-123',
67
+ });
68
+
69
+ await storage.listDatasets({
70
+ pagination: { page: 0, perPage: 20 },
71
+ filters: { organizationId: 'org_abc', projectId: 'project_xyz' },
72
+ });
73
+ ```
74
+
75
+ - Updated dependencies [[`5c4e9a4`](https://github.com/mastra-ai/mastra/commit/5c4e9a4cfb2216bb3ea7f8988ad3727f3b92bb3a), [`25961e3`](https://github.com/mastra-ai/mastra/commit/25961e3260ff3b1464637af8fcdb36210551c39f), [`7b29f33`](https://github.com/mastra-ai/mastra/commit/7b29f332a357a83e555f29e718e5f2fab9979943), [`24912b1`](https://github.com/mastra-ai/mastra/commit/24912b1f855d29ec36af4ef4bde1f7417e20cdf5), [`7686216`](https://github.com/mastra-ai/mastra/commit/7686216f37e74568feddec17cef3c3d24e10e60a), [`975c59a`](https://github.com/mastra-ai/mastra/commit/975c59ae363ee275fc55062392e1ffd2cbccbd53), [`d95f394`](https://github.com/mastra-ai/mastra/commit/d95f394fd24c8411886930d727679c4d5252aa26), [`f3f0c9d`](https://github.com/mastra-ai/mastra/commit/f3f0c9d7c878db5a13177871ce3523a14f14b311)]:
76
+ - @mastra/core@1.46.0-alpha.4
77
+
78
+ ## 1.10.1-alpha.0
79
+
80
+ ### Patch Changes
81
+
82
+ - Added storage for item-level tool mocks. Dataset items persist their `toolMocks` and experiment results persist their `toolMockReport`, so mocks and run diagnostics survive across sessions. ([#18036](https://github.com/mastra-ai/mastra/pull/18036))
83
+
84
+ - Updated dependencies [[`65f255a`](https://github.com/mastra-ai/mastra/commit/65f255a38667beb6ceeadabfa9eb5059bfec8298), [`4a88c6e`](https://github.com/mastra-ai/mastra/commit/4a88c6e2bdce316f8d7551b4ec3449b0b06fc71c), [`87a17ef`](https://github.com/mastra-ai/mastra/commit/87a17efbd725aca6639febdc5e69e2abb3048689), [`e11ff30`](https://github.com/mastra-ai/mastra/commit/e11ff301408bf1731dca2fb7fbfcd8c819500a35), [`9d2c946`](https://github.com/mastra-ai/mastra/commit/9d2c946d0859e90ae4bcec5beeb1da7398d2ad1e), [`f1ec385`](https://github.com/mastra-ai/mastra/commit/f1ec385386f62b1a0847ec5353ae2bb169d1c3d9), [`e14986f`](https://github.com/mastra-ai/mastra/commit/e14986f6e5478d6384d04ff9a7f9a79a46a8b529), [`0be490f`](https://github.com/mastra-ai/mastra/commit/0be490fabb538c5a7de796ea0aff7d04a0bea1f3), [`0be490f`](https://github.com/mastra-ai/mastra/commit/0be490fabb538c5a7de796ea0aff7d04a0bea1f3), [`974f614`](https://github.com/mastra-ai/mastra/commit/974f614e083bd68278536f94453f7b320b86a3c7), [`31be1cf`](https://github.com/mastra-ai/mastra/commit/31be1cf5f2a7b5eef12f6123a40653b4d8115c16)]:
85
+ - @mastra/core@1.46.0-alpha.3
86
+
3
87
  ## 1.10.0
4
88
 
5
89
  ### Minor Changes
@@ -3,7 +3,7 @@ name: mastra-mongodb
3
3
  description: Documentation for @mastra/mongodb. Use when working with @mastra/mongodb APIs, configuration, or implementation.
4
4
  metadata:
5
5
  package: "@mastra/mongodb"
6
- version: "1.10.0"
6
+ version: "1.11.0-alpha.1"
7
7
  ---
8
8
 
9
9
  ## When to use
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.10.0",
2
+ "version": "1.11.0-alpha.1",
3
3
  "package": "@mastra/mongodb",
4
4
  "exports": {},
5
5
  "modules": {}
package/dist/index.cjs CHANGED
@@ -15,7 +15,7 @@ var skills = require('@mastra/core/storage/domains/skills');
15
15
 
16
16
  // package.json
17
17
  var package_default = {
18
- version: "1.10.0"};
18
+ version: "1.11.0-alpha.1"};
19
19
  var MongoDBFilterTranslator = class extends filter.BaseFilterTranslator {
20
20
  getSupportedOperators() {
21
21
  return {
@@ -1930,7 +1930,22 @@ var MongoDBDatasetsStorage = class extends storage.DatasetsStorage {
1930
1930
  return [
1931
1931
  { collection: storage.TABLE_DATASETS, keys: { id: 1 }, options: { name: "idx_datasets_id", unique: true } },
1932
1932
  { collection: storage.TABLE_DATASETS, keys: { createdAt: -1, id: 1 }, options: { name: "idx_datasets_createdat_id" } },
1933
+ {
1934
+ collection: storage.TABLE_DATASETS,
1935
+ keys: { organizationId: 1, projectId: 1, createdAt: -1, id: 1 },
1936
+ options: { name: "idx_datasets_tenancy_createdat_id" }
1937
+ },
1938
+ {
1939
+ collection: storage.TABLE_DATASETS,
1940
+ keys: { organizationId: 1, projectId: 1, candidateKey: 1, candidateId: 1 },
1941
+ options: { name: "idx_datasets_tenancy_candidate" }
1942
+ },
1933
1943
  { collection: storage.TABLE_DATASET_ITEMS, keys: { datasetId: 1 }, options: { name: "idx_dataset_items_datasetid" } },
1944
+ {
1945
+ collection: storage.TABLE_DATASET_ITEMS,
1946
+ keys: { organizationId: 1, projectId: 1, datasetId: 1, validTo: 1, isDeleted: 1 },
1947
+ options: { name: "idx_dataset_items_tenancy_list" }
1948
+ },
1934
1949
  {
1935
1950
  collection: storage.TABLE_DATASET_ITEMS,
1936
1951
  keys: { datasetId: 1, validTo: 1 },
@@ -2008,6 +2023,10 @@ var MongoDBDatasetsStorage = class extends storage.DatasetsStorage {
2008
2023
  targetIds: typeof row.targetIds === "string" ? storage.safelyParseJSON(row.targetIds) : row.targetIds ?? void 0,
2009
2024
  scorerIds: typeof row.scorerIds === "string" ? storage.safelyParseJSON(row.scorerIds) : row.scorerIds ?? void 0,
2010
2025
  version: row.version ?? 0,
2026
+ organizationId: row.organizationId ?? null,
2027
+ projectId: row.projectId ?? null,
2028
+ candidateKey: row.candidateKey ?? null,
2029
+ candidateId: row.candidateId ?? null,
2011
2030
  createdAt: storage.ensureDate(row.createdAt),
2012
2031
  updatedAt: storage.ensureDate(row.updatedAt)
2013
2032
  };
@@ -2017,9 +2036,12 @@ var MongoDBDatasetsStorage = class extends storage.DatasetsStorage {
2017
2036
  id: row.id,
2018
2037
  datasetId: row.datasetId,
2019
2038
  datasetVersion: row.datasetVersion,
2039
+ organizationId: row.organizationId ?? null,
2040
+ projectId: row.projectId ?? null,
2020
2041
  input: typeof row.input === "string" ? storage.safelyParseJSON(row.input) : row.input,
2021
2042
  groundTruth: typeof row.groundTruth === "string" ? storage.safelyParseJSON(row.groundTruth) : row.groundTruth,
2022
2043
  expectedTrajectory: typeof row.expectedTrajectory === "string" ? storage.safelyParseJSON(row.expectedTrajectory) : row.expectedTrajectory,
2044
+ toolMocks: (typeof row.toolMocks === "string" ? storage.safelyParseJSON(row.toolMocks) : row.toolMocks) ?? void 0,
2023
2045
  requestContext: typeof row.requestContext === "string" ? storage.safelyParseJSON(row.requestContext) : row.requestContext,
2024
2046
  metadata: typeof row.metadata === "string" ? storage.safelyParseJSON(row.metadata) : row.metadata,
2025
2047
  source: typeof row.source === "string" ? storage.safelyParseJSON(row.source) : row.source,
@@ -2060,6 +2082,10 @@ var MongoDBDatasetsStorage = class extends storage.DatasetsStorage {
2060
2082
  targetIds: input.targetIds ?? null,
2061
2083
  scorerIds: input.scorerIds ?? null,
2062
2084
  version: 0,
2085
+ organizationId: input.organizationId ?? null,
2086
+ projectId: input.projectId ?? null,
2087
+ candidateKey: input.candidateKey ?? null,
2088
+ candidateId: input.candidateId ?? null,
2063
2089
  createdAt: now,
2064
2090
  updatedAt: now
2065
2091
  };
@@ -2170,7 +2196,12 @@ var MongoDBDatasetsStorage = class extends storage.DatasetsStorage {
2170
2196
  try {
2171
2197
  const { page, perPage: perPageInput } = args.pagination;
2172
2198
  const collection = await this.getCollection(storage.TABLE_DATASETS);
2173
- const total = await collection.countDocuments({});
2199
+ const filter = {};
2200
+ if (args.filters?.organizationId !== void 0) filter.organizationId = args.filters.organizationId;
2201
+ if (args.filters?.projectId !== void 0) filter.projectId = args.filters.projectId;
2202
+ if (args.filters?.candidateKey !== void 0) filter.candidateKey = args.filters.candidateKey;
2203
+ if (args.filters?.candidateId !== void 0) filter.candidateId = args.filters.candidateId;
2204
+ const total = await collection.countDocuments(filter);
2174
2205
  if (total === 0) {
2175
2206
  return { datasets: [], pagination: { total: 0, page, perPage: perPageInput, hasMore: false } };
2176
2207
  }
@@ -2180,7 +2211,7 @@ var MongoDBDatasetsStorage = class extends storage.DatasetsStorage {
2180
2211
  return { datasets: [], pagination: { total, page, perPage: perPageForResponse, hasMore: total > 0 } };
2181
2212
  }
2182
2213
  const limitValue = perPageInput === false ? total : perPage;
2183
- const rows = await collection.find({}).sort({ createdAt: -1, id: 1 }).skip(offset).limit(limitValue).toArray();
2214
+ const rows = await collection.find(filter).sort({ createdAt: -1, id: 1 }).skip(offset).limit(limitValue).toArray();
2184
2215
  return {
2185
2216
  datasets: rows.map((row) => this.transformDatasetRow(row)),
2186
2217
  pagination: {
@@ -2224,15 +2255,20 @@ var MongoDBDatasetsStorage = class extends storage.DatasetsStorage {
2224
2255
  });
2225
2256
  }
2226
2257
  const newVersion = result.version;
2258
+ const organizationId = result.organizationId ?? null;
2259
+ const projectId = result.projectId ?? null;
2227
2260
  await itemsCollection.insertOne({
2228
2261
  id,
2229
2262
  datasetId: args.datasetId,
2230
2263
  datasetVersion: newVersion,
2264
+ organizationId,
2265
+ projectId,
2231
2266
  validTo: null,
2232
2267
  isDeleted: false,
2233
2268
  input: args.input,
2234
2269
  groundTruth: args.groundTruth ?? null,
2235
2270
  expectedTrajectory: args.expectedTrajectory ?? null,
2271
+ toolMocks: args.toolMocks ?? null,
2236
2272
  requestContext: args.requestContext ?? null,
2237
2273
  metadata: args.metadata ?? null,
2238
2274
  source: args.source ?? null,
@@ -2249,9 +2285,12 @@ var MongoDBDatasetsStorage = class extends storage.DatasetsStorage {
2249
2285
  id,
2250
2286
  datasetId: args.datasetId,
2251
2287
  datasetVersion: newVersion,
2288
+ organizationId,
2289
+ projectId,
2252
2290
  input: args.input,
2253
2291
  groundTruth: args.groundTruth,
2254
2292
  expectedTrajectory: args.expectedTrajectory,
2293
+ toolMocks: args.toolMocks,
2255
2294
  requestContext: args.requestContext,
2256
2295
  metadata: args.metadata,
2257
2296
  source: args.source,
@@ -2289,7 +2328,7 @@ var MongoDBDatasetsStorage = class extends storage.DatasetsStorage {
2289
2328
  details: { itemId: args.id, expectedDatasetId: args.datasetId, actualDatasetId: existing.datasetId }
2290
2329
  });
2291
2330
  }
2292
- const hasChanges = args.input !== void 0 || args.groundTruth !== void 0 || args.expectedTrajectory !== void 0 || args.requestContext !== void 0 || args.metadata !== void 0 || args.source !== void 0;
2331
+ const hasChanges = args.input !== void 0 || args.groundTruth !== void 0 || args.expectedTrajectory !== void 0 || args.toolMocks !== void 0 || args.requestContext !== void 0 || args.metadata !== void 0 || args.source !== void 0;
2293
2332
  if (!hasChanges) {
2294
2333
  return existing;
2295
2334
  }
@@ -2298,6 +2337,7 @@ var MongoDBDatasetsStorage = class extends storage.DatasetsStorage {
2298
2337
  const mergedInput = args.input !== void 0 ? args.input : existing.input;
2299
2338
  const mergedGroundTruth = args.groundTruth !== void 0 ? args.groundTruth : existing.groundTruth;
2300
2339
  const mergedExpectedTrajectory = args.expectedTrajectory !== void 0 ? args.expectedTrajectory : existing.expectedTrajectory;
2340
+ const mergedToolMocks = args.toolMocks !== void 0 ? args.toolMocks : existing.toolMocks;
2301
2341
  const mergedRequestContext = args.requestContext !== void 0 ? args.requestContext : existing.requestContext;
2302
2342
  const mergedMetadata = args.metadata !== void 0 ? args.metadata : existing.metadata;
2303
2343
  const mergedSource = args.source !== void 0 ? args.source : existing.source;
@@ -2318,6 +2358,8 @@ var MongoDBDatasetsStorage = class extends storage.DatasetsStorage {
2318
2358
  });
2319
2359
  }
2320
2360
  const newVersion = result.version;
2361
+ const parentOrganizationId = result.organizationId ?? null;
2362
+ const parentProjectId = result.projectId ?? null;
2321
2363
  await itemsCollection.updateOne(
2322
2364
  { id: args.id, validTo: null, isDeleted: false },
2323
2365
  { $set: { validTo: newVersion } }
@@ -2326,11 +2368,14 @@ var MongoDBDatasetsStorage = class extends storage.DatasetsStorage {
2326
2368
  id: args.id,
2327
2369
  datasetId: args.datasetId,
2328
2370
  datasetVersion: newVersion,
2371
+ organizationId: parentOrganizationId,
2372
+ projectId: parentProjectId,
2329
2373
  validTo: null,
2330
2374
  isDeleted: false,
2331
2375
  input: mergedInput,
2332
2376
  groundTruth: mergedGroundTruth,
2333
2377
  expectedTrajectory: mergedExpectedTrajectory ?? null,
2378
+ toolMocks: mergedToolMocks ?? null,
2334
2379
  requestContext: mergedRequestContext,
2335
2380
  metadata: mergedMetadata,
2336
2381
  source: mergedSource,
@@ -2346,9 +2391,12 @@ var MongoDBDatasetsStorage = class extends storage.DatasetsStorage {
2346
2391
  return {
2347
2392
  ...existing,
2348
2393
  datasetVersion: newVersion,
2394
+ organizationId: parentOrganizationId,
2395
+ projectId: parentProjectId,
2349
2396
  input: mergedInput,
2350
2397
  groundTruth: mergedGroundTruth,
2351
2398
  expectedTrajectory: mergedExpectedTrajectory,
2399
+ toolMocks: mergedToolMocks,
2352
2400
  requestContext: mergedRequestContext,
2353
2401
  metadata: mergedMetadata,
2354
2402
  source: mergedSource,
@@ -2397,15 +2445,21 @@ var MongoDBDatasetsStorage = class extends storage.DatasetsStorage {
2397
2445
  });
2398
2446
  }
2399
2447
  const newVersion = result.version;
2448
+ const parentOrganizationId = result.organizationId ?? null;
2449
+ const parentProjectId = result.projectId ?? null;
2400
2450
  await itemsCollection.updateOne({ id, validTo: null, isDeleted: false }, { $set: { validTo: newVersion } });
2401
2451
  await itemsCollection.insertOne({
2402
2452
  id,
2403
2453
  datasetId,
2404
2454
  datasetVersion: newVersion,
2455
+ organizationId: parentOrganizationId,
2456
+ projectId: parentProjectId,
2405
2457
  validTo: null,
2406
2458
  isDeleted: true,
2407
2459
  input: existing.input,
2408
2460
  groundTruth: existing.groundTruth,
2461
+ expectedTrajectory: existing.expectedTrajectory ?? null,
2462
+ toolMocks: existing.toolMocks ?? null,
2409
2463
  requestContext: existing.requestContext,
2410
2464
  metadata: existing.metadata,
2411
2465
  source: existing.source,
@@ -2468,16 +2522,21 @@ var MongoDBDatasetsStorage = class extends storage.DatasetsStorage {
2468
2522
  });
2469
2523
  }
2470
2524
  const newVersion = result.version;
2525
+ const organizationId = result.organizationId ?? null;
2526
+ const projectId = result.projectId ?? null;
2471
2527
  if (itemsWithIds.length > 0) {
2472
2528
  const docs = itemsWithIds.map(({ generatedId, itemInput }) => ({
2473
2529
  id: generatedId,
2474
2530
  datasetId: input.datasetId,
2475
2531
  datasetVersion: newVersion,
2532
+ organizationId,
2533
+ projectId,
2476
2534
  validTo: null,
2477
2535
  isDeleted: false,
2478
2536
  input: itemInput.input,
2479
2537
  groundTruth: itemInput.groundTruth ?? null,
2480
2538
  expectedTrajectory: itemInput.expectedTrajectory ?? null,
2539
+ toolMocks: itemInput.toolMocks ?? null,
2481
2540
  requestContext: itemInput.requestContext ?? null,
2482
2541
  metadata: itemInput.metadata ?? null,
2483
2542
  source: itemInput.source ?? null,
@@ -2496,9 +2555,12 @@ var MongoDBDatasetsStorage = class extends storage.DatasetsStorage {
2496
2555
  id: generatedId,
2497
2556
  datasetId: input.datasetId,
2498
2557
  datasetVersion: newVersion,
2558
+ organizationId,
2559
+ projectId,
2499
2560
  input: itemInput.input,
2500
2561
  groundTruth: itemInput.groundTruth,
2501
2562
  expectedTrajectory: itemInput.expectedTrajectory,
2563
+ toolMocks: itemInput.toolMocks,
2502
2564
  requestContext: itemInput.requestContext,
2503
2565
  metadata: itemInput.metadata,
2504
2566
  source: itemInput.source,
@@ -2555,6 +2617,8 @@ var MongoDBDatasetsStorage = class extends storage.DatasetsStorage {
2555
2617
  });
2556
2618
  }
2557
2619
  const newVersion = result.version;
2620
+ const parentOrganizationId = result.organizationId ?? null;
2621
+ const parentProjectId = result.projectId ?? null;
2558
2622
  const currentIds = currentItems.map((i) => i.id);
2559
2623
  await itemsCollection.updateMany(
2560
2624
  { id: { $in: currentIds }, validTo: null, isDeleted: false },
@@ -2564,10 +2628,14 @@ var MongoDBDatasetsStorage = class extends storage.DatasetsStorage {
2564
2628
  id: item.id,
2565
2629
  datasetId: input.datasetId,
2566
2630
  datasetVersion: newVersion,
2631
+ organizationId: parentOrganizationId,
2632
+ projectId: parentProjectId,
2567
2633
  validTo: null,
2568
2634
  isDeleted: true,
2569
2635
  input: item.input,
2570
2636
  groundTruth: item.groundTruth,
2637
+ expectedTrajectory: item.expectedTrajectory ?? null,
2638
+ toolMocks: item.toolMocks ?? null,
2571
2639
  requestContext: item.requestContext,
2572
2640
  metadata: item.metadata,
2573
2641
  source: item.source,
@@ -2669,6 +2737,8 @@ var MongoDBDatasetsStorage = class extends storage.DatasetsStorage {
2669
2737
  const { page, perPage: perPageInput } = args.pagination;
2670
2738
  const collection = await this.getCollection(storage.TABLE_DATASET_ITEMS);
2671
2739
  const filter = { datasetId: args.datasetId };
2740
+ if (args.filters?.organizationId !== void 0) filter.organizationId = args.filters.organizationId;
2741
+ if (args.filters?.projectId !== void 0) filter.projectId = args.filters.projectId;
2672
2742
  if (args.version !== void 0) {
2673
2743
  filter.datasetVersion = { $lte: args.version };
2674
2744
  filter.$or = [{ validTo: null }, { validTo: { $gt: args.version } }];
@@ -2823,6 +2893,8 @@ function transformExperimentRow(row) {
2823
2893
  metadata: parseJsonField(row.metadata) ?? void 0,
2824
2894
  datasetId: row.datasetId ?? null,
2825
2895
  datasetVersion: row.datasetVersion != null ? Number(row.datasetVersion) : null,
2896
+ organizationId: row.organizationId ?? null,
2897
+ projectId: row.projectId ?? null,
2826
2898
  targetType: row.targetType,
2827
2899
  targetId: row.targetId,
2828
2900
  status: row.status,
@@ -2843,6 +2915,8 @@ function transformExperimentResultRow(row) {
2843
2915
  experimentId: row.experimentId,
2844
2916
  itemId: row.itemId,
2845
2917
  itemDatasetVersion: row.itemDatasetVersion != null ? Number(row.itemDatasetVersion) : null,
2918
+ organizationId: row.organizationId ?? null,
2919
+ projectId: row.projectId ?? null,
2846
2920
  input: parseJsonField(row.input),
2847
2921
  output: parseJsonField(row.output) ?? null,
2848
2922
  groundTruth: parseJsonField(row.groundTruth) ?? null,
@@ -2853,6 +2927,7 @@ function transformExperimentResultRow(row) {
2853
2927
  traceId: row.traceId ?? null,
2854
2928
  status: row.status ?? null,
2855
2929
  tags: Array.isArray(row.tags) ? row.tags : parseJsonField(row.tags) ?? null,
2930
+ toolMockReport: parseJsonField(row.toolMockReport) ?? null,
2856
2931
  createdAt: toDate(row.createdAt)
2857
2932
  };
2858
2933
  }
@@ -2880,11 +2955,14 @@ var MongoDBExperimentsStorage = class _MongoDBExperimentsStorage extends storage
2880
2955
  { collection: storage.TABLE_EXPERIMENTS, keys: { id: 1 }, options: { unique: true } },
2881
2956
  { collection: storage.TABLE_EXPERIMENTS, keys: { datasetId: 1 } },
2882
2957
  { collection: storage.TABLE_EXPERIMENTS, keys: { createdAt: -1, id: 1 } },
2958
+ // Tenancy: leading-tenant indexes for multi-tenant scans (parity with datasets domain).
2959
+ { collection: storage.TABLE_EXPERIMENTS, keys: { organizationId: 1, projectId: 1 } },
2883
2960
  { collection: storage.TABLE_EXPERIMENT_RESULTS, keys: { id: 1 }, options: { unique: true } },
2884
2961
  { collection: storage.TABLE_EXPERIMENT_RESULTS, keys: { experimentId: 1 } },
2885
2962
  { collection: storage.TABLE_EXPERIMENT_RESULTS, keys: { experimentId: 1, itemId: 1 }, options: { unique: true } },
2886
2963
  { collection: storage.TABLE_EXPERIMENT_RESULTS, keys: { createdAt: -1 } },
2887
- { collection: storage.TABLE_EXPERIMENT_RESULTS, keys: { experimentId: 1, startedAt: 1, id: 1 } }
2964
+ { collection: storage.TABLE_EXPERIMENT_RESULTS, keys: { experimentId: 1, startedAt: 1, id: 1 } },
2965
+ { collection: storage.TABLE_EXPERIMENT_RESULTS, keys: { organizationId: 1, projectId: 1 } }
2888
2966
  ];
2889
2967
  }
2890
2968
  async createDefaultIndexes() {
@@ -2926,6 +3004,8 @@ var MongoDBExperimentsStorage = class _MongoDBExperimentsStorage extends storage
2926
3004
  metadata: input.metadata ?? null,
2927
3005
  datasetId: input.datasetId ?? null,
2928
3006
  datasetVersion: input.datasetVersion ?? null,
3007
+ organizationId: input.organizationId ?? null,
3008
+ projectId: input.projectId ?? null,
2929
3009
  targetType: input.targetType,
2930
3010
  targetId: input.targetId,
2931
3011
  status: "pending",
@@ -2949,6 +3029,8 @@ var MongoDBExperimentsStorage = class _MongoDBExperimentsStorage extends storage
2949
3029
  metadata: input.metadata,
2950
3030
  datasetId: input.datasetId ?? null,
2951
3031
  datasetVersion: input.datasetVersion ?? null,
3032
+ organizationId: input.organizationId ?? null,
3033
+ projectId: input.projectId ?? null,
2952
3034
  targetType: input.targetType,
2953
3035
  targetId: input.targetId,
2954
3036
  status: "pending",
@@ -3050,6 +3132,15 @@ var MongoDBExperimentsStorage = class _MongoDBExperimentsStorage extends storage
3050
3132
  if (args.status) {
3051
3133
  filter.status = args.status;
3052
3134
  }
3135
+ if (args.filters) {
3136
+ const { organizationId, projectId } = args.filters;
3137
+ if (organizationId !== void 0) {
3138
+ filter.organizationId = organizationId;
3139
+ }
3140
+ if (projectId !== void 0) {
3141
+ filter.projectId = projectId;
3142
+ }
3143
+ }
3053
3144
  const total = await collection.countDocuments(filter);
3054
3145
  if (total === 0) {
3055
3146
  return { experiments: [], pagination: { total: 0, page, perPage: perPageInput, hasMore: false } };
@@ -3110,6 +3201,8 @@ var MongoDBExperimentsStorage = class _MongoDBExperimentsStorage extends storage
3110
3201
  experimentId: input.experimentId,
3111
3202
  itemId: input.itemId,
3112
3203
  itemDatasetVersion: input.itemDatasetVersion ?? null,
3204
+ organizationId: input.organizationId ?? null,
3205
+ projectId: input.projectId ?? null,
3113
3206
  input: input.input,
3114
3207
  output: input.output ?? null,
3115
3208
  groundTruth: input.groundTruth ?? null,
@@ -3120,6 +3213,7 @@ var MongoDBExperimentsStorage = class _MongoDBExperimentsStorage extends storage
3120
3213
  traceId: input.traceId ?? null,
3121
3214
  status: input.status ?? null,
3122
3215
  tags: input.tags ?? null,
3216
+ toolMockReport: input.toolMockReport ?? null,
3123
3217
  createdAt: now
3124
3218
  };
3125
3219
  try {
@@ -3130,6 +3224,8 @@ var MongoDBExperimentsStorage = class _MongoDBExperimentsStorage extends storage
3130
3224
  experimentId: input.experimentId,
3131
3225
  itemId: input.itemId,
3132
3226
  itemDatasetVersion: input.itemDatasetVersion ?? null,
3227
+ organizationId: input.organizationId ?? null,
3228
+ projectId: input.projectId ?? null,
3133
3229
  input: input.input,
3134
3230
  output: input.output ?? null,
3135
3231
  groundTruth: input.groundTruth ?? null,
@@ -3140,6 +3236,7 @@ var MongoDBExperimentsStorage = class _MongoDBExperimentsStorage extends storage
3140
3236
  traceId: input.traceId ?? null,
3141
3237
  status: input.status ?? null,
3142
3238
  tags: input.tags ?? null,
3239
+ toolMockReport: input.toolMockReport ?? null,
3143
3240
  createdAt: now
3144
3241
  };
3145
3242
  } catch (error$1) {
@@ -3228,6 +3325,15 @@ var MongoDBExperimentsStorage = class _MongoDBExperimentsStorage extends storage
3228
3325
  if (args.status) {
3229
3326
  filter.status = args.status;
3230
3327
  }
3328
+ if (args.filters) {
3329
+ const { organizationId, projectId } = args.filters;
3330
+ if (organizationId !== void 0) {
3331
+ filter.organizationId = organizationId;
3332
+ }
3333
+ if (projectId !== void 0) {
3334
+ filter.projectId = projectId;
3335
+ }
3336
+ }
3231
3337
  const total = await collection.countDocuments(filter);
3232
3338
  if (total === 0) {
3233
3339
  return { results: [], pagination: { total: 0, page, perPage: perPageInput, hasMore: false } };
@@ -6865,17 +6971,39 @@ Note: This migration may take some time for large collections.
6865
6971
  supported: ["batch-with-updates", "insert-only"]
6866
6972
  };
6867
6973
  }
6974
+ createDateRangeCondition(field, range) {
6975
+ const dateFilter = {};
6976
+ const stringFilter = {};
6977
+ if (range.start) {
6978
+ const operator = range.startExclusive ? "$gt" : "$gte";
6979
+ const start = range.start instanceof Date ? range.start : new Date(range.start);
6980
+ dateFilter[operator] = start;
6981
+ stringFilter[operator] = start.toISOString();
6982
+ }
6983
+ if (range.end) {
6984
+ const operator = range.endExclusive ? "$lt" : "$lte";
6985
+ const end = range.end instanceof Date ? range.end : new Date(range.end);
6986
+ dateFilter[operator] = end;
6987
+ stringFilter[operator] = end.toISOString();
6988
+ }
6989
+ if (Object.keys(dateFilter).length === 0) {
6990
+ return null;
6991
+ }
6992
+ return {
6993
+ $or: [{ [field]: dateFilter }, { [field]: stringFilter }]
6994
+ };
6995
+ }
6868
6996
  async createSpan(args) {
6869
6997
  const { span } = args;
6870
6998
  try {
6871
- const startedAt = span.startedAt instanceof Date ? span.startedAt.toISOString() : span.startedAt;
6872
- const endedAt = span.endedAt instanceof Date ? span.endedAt.toISOString() : span.endedAt;
6999
+ const startedAt = span.startedAt instanceof Date ? span.startedAt : new Date(span.startedAt);
7000
+ const endedAt = span.endedAt == null ? span.endedAt : span.endedAt instanceof Date ? span.endedAt : new Date(span.endedAt);
6873
7001
  const record = {
6874
7002
  ...span,
6875
7003
  startedAt,
6876
7004
  endedAt,
6877
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
6878
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
7005
+ createdAt: /* @__PURE__ */ new Date(),
7006
+ updatedAt: /* @__PURE__ */ new Date()
6879
7007
  };
6880
7008
  const collection = await this.getCollection(storage.TABLE_SPANS);
6881
7009
  await collection.insertOne(record);
@@ -7010,15 +7138,15 @@ Note: This migration may take some time for large collections.
7010
7138
  const { traceId, spanId, updates } = args;
7011
7139
  try {
7012
7140
  const data = { ...updates };
7013
- if (data.endedAt instanceof Date) {
7014
- data.endedAt = data.endedAt.toISOString();
7141
+ if (data.endedAt != null && !(data.endedAt instanceof Date)) {
7142
+ data.endedAt = new Date(data.endedAt);
7015
7143
  }
7016
- if (data.startedAt instanceof Date) {
7017
- data.startedAt = data.startedAt.toISOString();
7144
+ if (data.startedAt != null && !(data.startedAt instanceof Date)) {
7145
+ data.startedAt = new Date(data.startedAt);
7018
7146
  }
7019
7147
  const updateData = {
7020
7148
  ...data,
7021
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
7149
+ updatedAt: /* @__PURE__ */ new Date()
7022
7150
  };
7023
7151
  const collection = await this.getCollection(storage.TABLE_SPANS);
7024
7152
  await collection.updateOne({ spanId, traceId }, { $set: updateData });
@@ -7050,27 +7178,15 @@ Note: This migration may take some time for large collections.
7050
7178
  const andConditions = [];
7051
7179
  if (filters) {
7052
7180
  if (filters.startedAt) {
7053
- const startedAtFilter = {};
7054
- if (filters.startedAt.start) {
7055
- startedAtFilter.$gte = filters.startedAt.start.toISOString();
7056
- }
7057
- if (filters.startedAt.end) {
7058
- startedAtFilter.$lte = filters.startedAt.end.toISOString();
7059
- }
7060
- if (Object.keys(startedAtFilter).length > 0) {
7061
- mongoFilter.startedAt = startedAtFilter;
7181
+ const startedAtCondition = this.createDateRangeCondition("startedAt", filters.startedAt);
7182
+ if (startedAtCondition) {
7183
+ andConditions.push(startedAtCondition);
7062
7184
  }
7063
7185
  }
7064
7186
  if (filters.endedAt) {
7065
- const endedAtFilter = {};
7066
- if (filters.endedAt.start) {
7067
- endedAtFilter.$gte = filters.endedAt.start.toISOString();
7068
- }
7069
- if (filters.endedAt.end) {
7070
- endedAtFilter.$lte = filters.endedAt.end.toISOString();
7071
- }
7072
- if (Object.keys(endedAtFilter).length > 0) {
7073
- andConditions.push({ endedAt: endedAtFilter });
7187
+ const endedAtCondition = this.createDateRangeCondition("endedAt", filters.endedAt);
7188
+ if (endedAtCondition) {
7189
+ andConditions.push(endedAtCondition);
7074
7190
  }
7075
7191
  }
7076
7192
  if (filters.spanType !== void 0) {
@@ -7278,14 +7394,14 @@ Note: This migration may take some time for large collections.
7278
7394
  async batchCreateSpans(args) {
7279
7395
  try {
7280
7396
  const records = args.records.map((record) => {
7281
- const startedAt = record.startedAt instanceof Date ? record.startedAt.toISOString() : record.startedAt;
7282
- const endedAt = record.endedAt instanceof Date ? record.endedAt.toISOString() : record.endedAt;
7397
+ const startedAt = record.startedAt instanceof Date ? record.startedAt : new Date(record.startedAt);
7398
+ const endedAt = record.endedAt == null ? record.endedAt : record.endedAt instanceof Date ? record.endedAt : new Date(record.endedAt);
7283
7399
  return {
7284
7400
  ...record,
7285
7401
  startedAt,
7286
7402
  endedAt,
7287
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
7288
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
7403
+ createdAt: /* @__PURE__ */ new Date(),
7404
+ updatedAt: /* @__PURE__ */ new Date()
7289
7405
  };
7290
7406
  });
7291
7407
  if (records.length > 0) {
@@ -7310,15 +7426,15 @@ Note: This migration may take some time for large collections.
7310
7426
  }
7311
7427
  const bulkOps = args.records.map((record) => {
7312
7428
  const data = { ...record.updates };
7313
- if (data.endedAt instanceof Date) {
7314
- data.endedAt = data.endedAt.toISOString();
7429
+ if (data.endedAt != null && !(data.endedAt instanceof Date)) {
7430
+ data.endedAt = new Date(data.endedAt);
7315
7431
  }
7316
- if (data.startedAt instanceof Date) {
7317
- data.startedAt = data.startedAt.toISOString();
7432
+ if (data.startedAt != null && !(data.startedAt instanceof Date)) {
7433
+ data.startedAt = new Date(data.startedAt);
7318
7434
  }
7319
7435
  const updateData = {
7320
7436
  ...data,
7321
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
7437
+ updatedAt: /* @__PURE__ */ new Date()
7322
7438
  };
7323
7439
  return {
7324
7440
  updateOne: {