@mastra/spanner 1.5.0 → 1.6.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,61 @@
1
1
  # @mastra/spanner
2
2
 
3
+ ## 1.6.0-alpha.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Fixed resource-scoped message includes across storage adapters so included context cannot cross resource boundaries. ([#20984](https://github.com/mastra-ai/mastra/pull/20984))
8
+
9
+ - Updated dependencies [[`6445eba`](https://github.com/mastra-ai/mastra/commit/6445eba6020abac681aba1cc9289f446cb400cbe), [`df31eb0`](https://github.com/mastra-ai/mastra/commit/df31eb0c7087d782a0d9346e467f9a4af4b0eef6), [`fcd0667`](https://github.com/mastra-ai/mastra/commit/fcd0667a4e378be35c9a1b1eb19cce78fbfd7282), [`bab06b1`](https://github.com/mastra-ai/mastra/commit/bab06b18923873a584bdfc71a6b4ec7fb4727fb7)]:
10
+ - @mastra/core@1.58.0-alpha.5
11
+
12
+ ## 1.6.0-alpha.0
13
+
14
+ ### Minor Changes
15
+
16
+ - Added experiment provenance and grouping support to the LibSQL, MongoDB, MySQL, PostgreSQL, and Spanner storage adapters. These fields remain available for later grouping and filtering. ([#20645](https://github.com/mastra-ai/mastra/pull/20645))
17
+
18
+ ```ts
19
+ import { PostgresStore } from '@mastra/pg';
20
+
21
+ const storage = new PostgresStore({
22
+ id: 'postgres-storage',
23
+ connectionString: process.env.DATABASE_URL!,
24
+ });
25
+
26
+ await dataset.startExperiment({
27
+ task,
28
+ scorers,
29
+ provenance: { source: 'github', sourceVersion: 'abc123' },
30
+ grouping: { experimentSetId: 'benchmark-1', variantId: 'candidate', trialIndex: 0 },
31
+ });
32
+ ```
33
+
34
+ - Memory list reads now surface database errors instead of silently returning empty results. ([#17910](https://github.com/mastra-ai/mastra/pull/17910))
35
+
36
+ Previously, the paginated memory reads (`listThreads`, `listMessages`, `listMessagesByResourceId`, and `listMessagesById`) caught backend failures, logged them, and returned an empty payload like `{ threads: [], total: 0, hasMore: false }`. A transient outage (locked table, dropped connection) was therefore indistinguishable from a genuinely empty result, so an agent reading conversation history during a brief failure would treat it as "no history" and could overwrite real state. These methods now re-throw the failure as a `MastraError`. Validation (USER) errors and genuinely empty results are unchanged.
37
+
38
+ **Behavior change**
39
+
40
+ Callers that previously received an empty result on a backend failure will now receive a thrown `MastraError`. If you call these read methods directly (rather than through an agent, which already surfaces errors), wrap them so a transient outage doesn't crash the caller:
41
+
42
+ ```ts
43
+ try {
44
+ const { threads } = await storage.listThreads({ resourceId });
45
+ // ...use threads
46
+ } catch (error) {
47
+ // a real backend failure. Decide whether to retry, surface, or degrade.
48
+ // An empty thread list no longer hides here; it only means "no threads".
49
+ }
50
+ ```
51
+
52
+ ### Patch Changes
53
+
54
+ - dependencies updates: ([#20409](https://github.com/mastra-ai/mastra/pull/20409))
55
+ - Updated dependency [`@google-cloud/spanner@^8.10.0` ↗︎](https://www.npmjs.com/package/@google-cloud/spanner/v/8.10.0) (from `^8.9.0`, in `dependencies`)
56
+ - Updated dependencies [[`e7109ee`](https://github.com/mastra-ai/mastra/commit/e7109ee6f731bacc79c885906f3c7dca8d8f013a), [`772c0c8`](https://github.com/mastra-ai/mastra/commit/772c0c897cec383258de2e6178147f8014767c7b), [`578bf2e`](https://github.com/mastra-ai/mastra/commit/578bf2e6a88e9d5b8bf502204e15a95dfbb679ae), [`06b2d87`](https://github.com/mastra-ai/mastra/commit/06b2d87e63bcdd0ed59215c6789692b9b12de376), [`ac01d63`](https://github.com/mastra-ai/mastra/commit/ac01d6355974aec73fdb8781449ed12bac582094), [`a810a05`](https://github.com/mastra-ai/mastra/commit/a810a058f62ad407cfc1701e0be36ae91145d7cf), [`f8da216`](https://github.com/mastra-ai/mastra/commit/f8da21633e7eb0e31c9ce0fc30567870d19416d3), [`6104347`](https://github.com/mastra-ai/mastra/commit/61043473ba6bfd0a25156824e853e13165562e6c), [`45bfb88`](https://github.com/mastra-ai/mastra/commit/45bfb88fd52f1dd3be20e2a38905777c96499c90), [`e3b9307`](https://github.com/mastra-ai/mastra/commit/e3b9307098daefbfae2a52ae2ef51bc9fc701190), [`d6834c5`](https://github.com/mastra-ai/mastra/commit/d6834c5a7866b16734d23900163c2414ed70d791), [`c52d346`](https://github.com/mastra-ai/mastra/commit/c52d3462ec831a5d95926ecd3d3373f5928ad2e5), [`0023e79`](https://github.com/mastra-ai/mastra/commit/0023e7919431078280abd11c89d1edeae35fcc69), [`c2ad51e`](https://github.com/mastra-ai/mastra/commit/c2ad51e2467f901eecba8c9f4a45e22a50bd7c18), [`3dc97ea`](https://github.com/mastra-ai/mastra/commit/3dc97ea415fad353b48a13095fad1835933cc12a), [`3d01cd3`](https://github.com/mastra-ai/mastra/commit/3d01cd387321b6f9c5cac31d487c84bf51b19c78), [`7bf3086`](https://github.com/mastra-ai/mastra/commit/7bf308663f0115ca74ad20554ade740f06640859), [`a8dd139`](https://github.com/mastra-ai/mastra/commit/a8dd1391a9fe9a6632c25809ef236980afa9a020), [`e5786be`](https://github.com/mastra-ai/mastra/commit/e5786be02bb903073082bd9d6da880ebaacc343f), [`2093fbd`](https://github.com/mastra-ai/mastra/commit/2093fbd53bb744bae19ec89f6d73db9a66fbe8a7), [`e7a5da4`](https://github.com/mastra-ai/mastra/commit/e7a5da4ef8e4dd452d2f232961b4e682a85ffe43), [`7b4393d`](https://github.com/mastra-ai/mastra/commit/7b4393d557411fdcf07b0e30e5acaf7cc85154ae)]:
57
+ - @mastra/core@1.58.0-alpha.1
58
+
3
59
  ## 1.5.0
4
60
 
5
61
  ### Minor Changes
@@ -3,7 +3,7 @@ name: mastra-spanner
3
3
  description: Documentation for @mastra/spanner. Use when working with @mastra/spanner APIs, configuration, or implementation.
4
4
  metadata:
5
5
  package: "@mastra/spanner"
6
- version: "1.5.0"
6
+ version: "1.6.0-alpha.1"
7
7
  ---
8
8
 
9
9
  ## When to use
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.5.0",
2
+ "version": "1.6.0-alpha.1",
3
3
  "package": "@mastra/spanner",
4
4
  "exports": {},
5
5
  "modules": {}
package/dist/index.cjs CHANGED
@@ -3971,6 +3971,12 @@ function rowToExperiment(row) {
3971
3971
  name: t.name ?? void 0,
3972
3972
  description: t.description ?? void 0,
3973
3973
  metadata: t.metadata ?? void 0,
3974
+ provenance: t.provenance ?? null,
3975
+ runnerAttestation: t.runnerAttestation ?? null,
3976
+ experimentSetId: t.experimentSetId ?? null,
3977
+ comparisonId: t.comparisonId ?? null,
3978
+ variantId: t.variantId ?? null,
3979
+ trialIndex: t.trialIndex == null ? null : Number(t.trialIndex),
3974
3980
  datasetId: t.datasetId ?? null,
3975
3981
  datasetVersion: t.datasetVersion == null ? null : Number(t.datasetVersion),
3976
3982
  organizationId: t.organizationId ?? null,
@@ -4051,7 +4057,17 @@ var ExperimentsSpanner = class ExperimentsSpanner extends _mastra_core_storage.E
4051
4057
  await this.db.alterTable({
4052
4058
  tableName: _mastra_core_storage.TABLE_EXPERIMENTS,
4053
4059
  schema: _mastra_core_storage.TABLE_SCHEMAS[_mastra_core_storage.TABLE_EXPERIMENTS],
4054
- ifNotExists: ["organizationId", "projectId"]
4060
+ ifNotExists: [
4061
+ "agentVersion",
4062
+ "organizationId",
4063
+ "projectId",
4064
+ "provenance",
4065
+ "runnerAttestation",
4066
+ "experimentSetId",
4067
+ "comparisonId",
4068
+ "variantId",
4069
+ "trialIndex"
4070
+ ]
4055
4071
  });
4056
4072
  await this.db.alterTable({
4057
4073
  tableName: _mastra_core_storage.TABLE_EXPERIMENT_RESULTS,
@@ -4072,6 +4088,16 @@ var ExperimentsSpanner = class ExperimentsSpanner extends _mastra_core_storage.E
4072
4088
  table: _mastra_core_storage.TABLE_EXPERIMENTS,
4073
4089
  columns: ["datasetId"]
4074
4090
  },
4091
+ {
4092
+ name: "mastra_experiments_grouping_idx",
4093
+ table: _mastra_core_storage.TABLE_EXPERIMENTS,
4094
+ columns: [
4095
+ "experimentSetId",
4096
+ "comparisonId",
4097
+ "variantId",
4098
+ "trialIndex"
4099
+ ]
4100
+ },
4075
4101
  {
4076
4102
  name: "mastra_experiment_results_experimentid_idx",
4077
4103
  table: _mastra_core_storage.TABLE_EXPERIMENT_RESULTS,
@@ -4116,6 +4142,12 @@ var ExperimentsSpanner = class ExperimentsSpanner extends _mastra_core_storage.E
4116
4142
  name: input.name ?? void 0,
4117
4143
  description: input.description ?? void 0,
4118
4144
  metadata: input.metadata ?? void 0,
4145
+ provenance: input.provenance ?? null,
4146
+ runnerAttestation: input.runnerAttestation ?? null,
4147
+ experimentSetId: input.experimentSetId ?? null,
4148
+ comparisonId: input.comparisonId ?? null,
4149
+ variantId: input.variantId ?? null,
4150
+ trialIndex: input.trialIndex ?? null,
4119
4151
  datasetId: input.datasetId ?? null,
4120
4152
  datasetVersion: input.datasetVersion ?? null,
4121
4153
  organizationId: input.organizationId ?? null,
@@ -4140,6 +4172,12 @@ var ExperimentsSpanner = class ExperimentsSpanner extends _mastra_core_storage.E
4140
4172
  name: experiment.name ?? null,
4141
4173
  description: experiment.description ?? null,
4142
4174
  metadata: experiment.metadata ?? null,
4175
+ provenance: experiment.provenance,
4176
+ runnerAttestation: experiment.runnerAttestation,
4177
+ experimentSetId: experiment.experimentSetId,
4178
+ comparisonId: experiment.comparisonId,
4179
+ variantId: experiment.variantId,
4180
+ trialIndex: experiment.trialIndex,
4143
4181
  datasetId: experiment.datasetId,
4144
4182
  datasetVersion: experiment.datasetVersion,
4145
4183
  organizationId: experiment.organizationId,
@@ -4274,6 +4312,22 @@ var ExperimentsSpanner = class ExperimentsSpanner extends _mastra_core_storage.E
4274
4312
  conditions.push(`${quoteIdent("status", "column name")} = @status`);
4275
4313
  params.status = args.status;
4276
4314
  }
4315
+ if (args.experimentSetId !== void 0) {
4316
+ conditions.push(`${quoteIdent("experimentSetId", "column name")} = @experimentSetId`);
4317
+ params.experimentSetId = args.experimentSetId;
4318
+ }
4319
+ if (args.comparisonId !== void 0) {
4320
+ conditions.push(`${quoteIdent("comparisonId", "column name")} = @comparisonId`);
4321
+ params.comparisonId = args.comparisonId;
4322
+ }
4323
+ if (args.variantId !== void 0) {
4324
+ conditions.push(`${quoteIdent("variantId", "column name")} = @variantId`);
4325
+ params.variantId = args.variantId;
4326
+ }
4327
+ if (args.trialIndex !== void 0) {
4328
+ conditions.push(`${quoteIdent("trialIndex", "column name")} = @trialIndex`);
4329
+ params.trialIndex = args.trialIndex;
4330
+ }
4277
4331
  if (args.filters) {
4278
4332
  const { organizationId, projectId } = args.filters;
4279
4333
  if (organizationId !== void 0) {
@@ -6681,15 +6735,23 @@ var MemorySpanner = class MemorySpanner extends _mastra_core_storage.MemoryStora
6681
6735
  }, error);
6682
6736
  this.logger?.error?.(mastraError.toString());
6683
6737
  this.logger?.trackException?.(mastraError);
6684
- return { messages: [] };
6738
+ throw mastraError;
6685
6739
  }
6686
6740
  }
6687
- /** Resolves the `include` clause: pinned messages plus their before/after windows. */
6688
- async getIncludedMessages({ include }) {
6741
+ /**
6742
+ * Resolves the `include` clause: pinned messages plus their before/after windows.
6743
+ *
6744
+ * @param include - Message ids to pin, each with an optional before/after window.
6745
+ * @param resourceId - When set, restricts both the pinned messages and their context
6746
+ * to that resource so an id from another resource returns nothing.
6747
+ */
6748
+ async getIncludedMessages({ include, resourceId }) {
6689
6749
  if (!include || include.length === 0) return null;
6750
+ const resourceCondition = resourceId ? ` AND ${quoteIdent("resourceId", "column name")} = @scopedResourceId` : "";
6751
+ const resourceParams = resourceId ? { scopedResourceId: resourceId } : {};
6690
6752
  const ids = include.map((i) => i.id);
6691
6753
  const placeholders = [];
6692
- const idParams = {};
6754
+ const idParams = { ...resourceParams };
6693
6755
  ids.forEach((id, i) => {
6694
6756
  const name = `tid${i}`;
6695
6757
  placeholders.push(`@${name}`);
@@ -6697,7 +6759,7 @@ var MemorySpanner = class MemorySpanner extends _mastra_core_storage.MemoryStora
6697
6759
  });
6698
6760
  const targetsSql = `SELECT id, content, role, type, ${quoteIdent("createdAt", "column name")}, ${quoteIdent("thread_id", "column name")} AS threadId, ${quoteIdent("resourceId", "column name")}
6699
6761
  FROM ${quoteIdent(_mastra_core_storage.TABLE_MESSAGES, "table name")}
6700
- WHERE id IN (${placeholders.join(", ")})`;
6762
+ WHERE id IN (${placeholders.join(", ")})${resourceCondition}`;
6701
6763
  const [targetRows] = await this.database.run({
6702
6764
  sql: targetsSql,
6703
6765
  params: idParams,
@@ -6722,14 +6784,15 @@ var MemorySpanner = class MemorySpanner extends _mastra_core_storage.MemoryStora
6722
6784
  sql: `SELECT id, content, role, type, ${quoteIdent("createdAt", "column name")}, ${quoteIdent("thread_id", "column name")} AS threadId, ${quoteIdent("resourceId", "column name")}
6723
6785
  FROM ${quoteIdent(_mastra_core_storage.TABLE_MESSAGES, "table name")}
6724
6786
  WHERE ${quoteIdent("thread_id", "column name")} = @threadId
6725
- AND (${quoteIdent("createdAt", "column name")} < @ts OR (${quoteIdent("createdAt", "column name")} = @ts AND id < @id))
6787
+ AND (${quoteIdent("createdAt", "column name")} < @ts OR (${quoteIdent("createdAt", "column name")} = @ts AND id < @id))${resourceCondition}
6726
6788
  ORDER BY ${quoteIdent("createdAt", "column name")} DESC, id DESC
6727
6789
  LIMIT @lim`,
6728
6790
  params: {
6729
6791
  threadId,
6730
6792
  ts: targetCreatedAt,
6731
6793
  id: target.id,
6732
- lim: withPreviousMessages
6794
+ lim: withPreviousMessages,
6795
+ ...resourceParams
6733
6796
  },
6734
6797
  json: true
6735
6798
  });
@@ -6743,14 +6806,15 @@ var MemorySpanner = class MemorySpanner extends _mastra_core_storage.MemoryStora
6743
6806
  sql: `SELECT id, content, role, type, ${quoteIdent("createdAt", "column name")}, ${quoteIdent("thread_id", "column name")} AS threadId, ${quoteIdent("resourceId", "column name")}
6744
6807
  FROM ${quoteIdent(_mastra_core_storage.TABLE_MESSAGES, "table name")}
6745
6808
  WHERE ${quoteIdent("thread_id", "column name")} = @threadId
6746
- AND (${quoteIdent("createdAt", "column name")} > @ts OR (${quoteIdent("createdAt", "column name")} = @ts AND id > @id))
6809
+ AND (${quoteIdent("createdAt", "column name")} > @ts OR (${quoteIdent("createdAt", "column name")} = @ts AND id > @id))${resourceCondition}
6747
6810
  ORDER BY ${quoteIdent("createdAt", "column name")} ASC, id ASC
6748
6811
  LIMIT @lim`,
6749
6812
  params: {
6750
6813
  threadId,
6751
6814
  ts: targetCreatedAt,
6752
6815
  id: target.id,
6753
- lim: withNextMessages
6816
+ lim: withNextMessages,
6817
+ ...resourceParams
6754
6818
  },
6755
6819
  json: true
6756
6820
  });
@@ -6803,7 +6867,10 @@ var MemorySpanner = class MemorySpanner extends _mastra_core_storage.MemoryStora
6803
6867
  hasMore: false
6804
6868
  };
6805
6869
  if (perPage === 0 && include && include.length > 0) {
6806
- const includeMessages = await this.getIncludedMessages({ include }) ?? [];
6870
+ const includeMessages = await this.getIncludedMessages({
6871
+ include,
6872
+ resourceId
6873
+ }) ?? [];
6807
6874
  const parsedIncludes = this.parseAndFormatMessages(includeMessages, "v2");
6808
6875
  const dirMul = direction === "ASC" ? 1 : -1;
6809
6876
  return {
@@ -6861,7 +6928,10 @@ var MemorySpanner = class MemorySpanner extends _mastra_core_storage.MemoryStora
6861
6928
  };
6862
6929
  if (include?.length) {
6863
6930
  const seen = new Set(messages.map((m) => m.id));
6864
- (await this.getIncludedMessages({ include }))?.forEach((msg) => {
6931
+ (await this.getIncludedMessages({
6932
+ include,
6933
+ resourceId
6934
+ }))?.forEach((msg) => {
6865
6935
  if (!seen.has(msg.id)) {
6866
6936
  messages.push(msg);
6867
6937
  seen.add(msg.id);