@mastra/spanner 1.5.0-alpha.2 → 1.6.0-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,127 @@
1
1
  # @mastra/spanner
2
2
 
3
+ ## 1.6.0-alpha.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 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))
8
+
9
+ ```ts
10
+ import { PostgresStore } from '@mastra/pg';
11
+
12
+ const storage = new PostgresStore({
13
+ id: 'postgres-storage',
14
+ connectionString: process.env.DATABASE_URL!,
15
+ });
16
+
17
+ await dataset.startExperiment({
18
+ task,
19
+ scorers,
20
+ provenance: { source: 'github', sourceVersion: 'abc123' },
21
+ grouping: { experimentSetId: 'benchmark-1', variantId: 'candidate', trialIndex: 0 },
22
+ });
23
+ ```
24
+
25
+ - Memory list reads now surface database errors instead of silently returning empty results. ([#17910](https://github.com/mastra-ai/mastra/pull/17910))
26
+
27
+ 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.
28
+
29
+ **Behavior change**
30
+
31
+ 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:
32
+
33
+ ```ts
34
+ try {
35
+ const { threads } = await storage.listThreads({ resourceId });
36
+ // ...use threads
37
+ } catch (error) {
38
+ // a real backend failure. Decide whether to retry, surface, or degrade.
39
+ // An empty thread list no longer hides here; it only means "no threads".
40
+ }
41
+ ```
42
+
43
+ ### Patch Changes
44
+
45
+ - dependencies updates: ([#20409](https://github.com/mastra-ai/mastra/pull/20409))
46
+ - 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`)
47
+ - 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)]:
48
+ - @mastra/core@1.58.0-alpha.1
49
+
50
+ ## 1.5.0
51
+
52
+ ### Minor Changes
53
+
54
+ - Added batch trace ID filtering to observability metric queries. ([#20535](https://github.com/mastra-ai/mastra/pull/20535))
55
+
56
+ ```ts
57
+ const result = await observability.getMetricBreakdown({
58
+ name: ['mastra_model_total_input_tokens'],
59
+ aggregation: 'sum',
60
+ groupBy: ['traceId'],
61
+ filters: { traceIds: ['trace-1', 'trace-2'] },
62
+ });
63
+ ```
64
+
65
+ - Added persistence for dataset item undeclared tool policies. ([#19643](https://github.com/mastra-ai/mastra/pull/19643))
66
+
67
+ ```typescript
68
+ await dataset.addItem({
69
+ input: 'What is the weather?',
70
+ unmockedToolPolicy: 'deny',
71
+ });
72
+ ```
73
+
74
+ - Stored workflow definitions now persist across restarts on every major database backend. ([#20471](https://github.com/mastra-ai/mastra/pull/20471))
75
+
76
+ Implement the `workflowDefinitions` storage domain for libsql, pg, mysql, mssql, mongodb, and spanner. Previously the stored-workflow persistence path (`POST /stored/workflows`, `Mastra.addStoredWorkflow`) only worked against `@mastra/core`'s in-memory store. Persistent adapters returned `undefined` from `storage.getStore('workflowDefinitions')` and threw when the HTTP handler tried to read/write a workflow.
77
+
78
+ ```ts
79
+ const workflowDefinitions = await storage.getStore('workflowDefinitions');
80
+ if (!workflowDefinitions) {
81
+ throw new Error('This storage adapter does not support the workflowDefinitions domain');
82
+ }
83
+
84
+ await workflowDefinitions.upsert({
85
+ id: 'greeting-workflow',
86
+ inputSchema: { type: 'object', properties: { name: { type: 'string' } }, required: ['name'] },
87
+ outputSchema: { type: 'object', properties: { text: { type: 'string' } }, required: ['text'] },
88
+ graph: [{ type: 'agent', id: 'greet', agentId: 'greeter-agent' }],
89
+ });
90
+
91
+ const { definitions, total } = await workflowDefinitions.list({ status: 'active' });
92
+ const definition = await workflowDefinitions.get('greeting-workflow');
93
+ await workflowDefinitions.delete('greeting-workflow');
94
+ ```
95
+
96
+ Each adapter now ships a `WorkflowDefinitions*` domain that:
97
+
98
+ - Creates the shared `mastra_workflow_definitions` table (or Mongo collection) from `WORKFLOW_DEFINITIONS_SCHEMA` during `init()`, plus a default index on `status`.
99
+ - Implements `upsert` / `get` / `list` / `delete` matching `WorkflowDefinitionsStorage` semantics (`list` supports `status` and `authorId` filters and orders by `updatedAt` desc). Partial upserts preserve unspecified fields, including `authorId` updates and `createdAt` / `updatedAt` semantics.
100
+ - Handles concurrent first-writes race-safely: if two callers upsert the same new id simultaneously, the losing insert detects the duplicate key, re-reads the row, and applies the partial-update path instead of failing.
101
+ - Round-trips the JSON columns (`inputSchema`, `outputSchema`, `stateSchema`, `requestContextSchema`, `metadata`, `graph`) through each adapter's JSON handling, so declarative workflow graphs rehydrate identically no matter which backend they were stored in. Malformed persisted JSON surfaces as an actionable error naming the row and column instead of hydrating raw strings.
102
+
103
+ Exported class names by adapter: `WorkflowDefinitionsLibSQL`, `WorkflowDefinitionsPG`, `WorkflowDefinitionsMySQL`, `WorkflowDefinitionsMSSQL`, `MongoDBWorkflowDefinitionsStore`, `WorkflowDefinitionsSpanner`. The composite stores (`LibSQLStore`, `PostgresStore`, `MySQLStore`, `MSSQLStore`, `MongoDBStore`, `SpannerStore`) auto-wire the new domain, so callers do not need to construct it manually — `storage.getStore('workflowDefinitions')` now returns a live handle.
104
+
105
+ The pg adapter reads `createdAt` / `updatedAt` from the auto-added `createdAtZ` / `updatedAtZ` `timestamptz` companion columns to avoid the naive-timestamp / local-TZ drift that a plain `TIMESTAMP` read exhibits under node-pg.
106
+
107
+ `@mastra/clickhouse` and `@mastra/cloudflare` register the new `mastra_workflow_definitions` table in their table/type maps so shared table constants stay exhaustive (no workflow-definitions domain implementation yet).
108
+
109
+ ### Patch Changes
110
+
111
+ - Added a comment column to experiment results so review comments persist. The column is added automatically and non-destructively on startup for existing databases (https://github.com/mastra-ai/mastra/issues/19857). ([#19865](https://github.com/mastra-ai/mastra/pull/19865))
112
+
113
+ - Dataset item scorer selections now persist across Spanner writes and reads. Setting `scorerIds` to `null` clears an item override, while `[]` remains an explicit override with no scorers. ([#20191](https://github.com/mastra-ai/mastra/pull/20191))
114
+
115
+ ```typescript
116
+ await dataset.addItem({
117
+ input: 'Evaluate this response',
118
+ scorerIds: [],
119
+ });
120
+ ```
121
+
122
+ - Updated dependencies [[`4844167`](https://github.com/mastra-ai/mastra/commit/4844167cff2d5ec5004e94edd34970833040fa3f), [`c5e56ff`](https://github.com/mastra-ai/mastra/commit/c5e56ff3bcabdf062708f2d48744fec304df6792), [`594f7b2`](https://github.com/mastra-ai/mastra/commit/594f7b28f5263fb9982fd50d95c471fb971ea984), [`7f4e26d`](https://github.com/mastra-ai/mastra/commit/7f4e26dd57bd9b23c278ea21235ab823a3810a6c), [`311f943`](https://github.com/mastra-ai/mastra/commit/311f943bee60e8fdf5c84499ea50e884276c936c), [`322daa6`](https://github.com/mastra-ai/mastra/commit/322daa6d90552909204044790d850958f6745fed), [`db4e6ff`](https://github.com/mastra-ai/mastra/commit/db4e6ff744503112eb64deeaf6c2b54bf26a54c7), [`5faf93f`](https://github.com/mastra-ai/mastra/commit/5faf93f03e19daea394b9e2a923f2e4f833407f2), [`82201f7`](https://github.com/mastra-ai/mastra/commit/82201f75fae8e050a8de2df08b74875ee74c6b83), [`cadaa13`](https://github.com/mastra-ai/mastra/commit/cadaa1372e1077c8e85eb64c5499ba8803caa323), [`0c89896`](https://github.com/mastra-ai/mastra/commit/0c8989673fb7d106837098398131e570c6023b68), [`6d19a65`](https://github.com/mastra-ai/mastra/commit/6d19a6517f5da3911023d446b7e2d5dad8adb1cb), [`23b4238`](https://github.com/mastra-ai/mastra/commit/23b423844ad0bcf2a502a68dd62866d6160f9f6d), [`80ad891`](https://github.com/mastra-ai/mastra/commit/80ad891f8cd10379aa5b5af7510c763783b2ab56), [`fb18da5`](https://github.com/mastra-ai/mastra/commit/fb18da56fc35689ae370621a8f10b5b0d8606e20), [`fb18da5`](https://github.com/mastra-ai/mastra/commit/fb18da56fc35689ae370621a8f10b5b0d8606e20), [`e320a76`](https://github.com/mastra-ai/mastra/commit/e320a763feaf65c6be3cebecf746defcbde161b3), [`03b4918`](https://github.com/mastra-ai/mastra/commit/03b4918c80d188ce375334c393e131c6e94bd7eb), [`14ef73a`](https://github.com/mastra-ai/mastra/commit/14ef73a4bbd73e7808414816eb0628ce1d80b5d7), [`b582f7f`](https://github.com/mastra-ai/mastra/commit/b582f7fa2f9c1f87d19efc63d344fbe5dda2608c), [`0a6598b`](https://github.com/mastra-ai/mastra/commit/0a6598bde80bde008986ad6616bed9632b9294cb), [`06000d7`](https://github.com/mastra-ai/mastra/commit/06000d73712911572e913b8a83339270296d0a22), [`1d677d5`](https://github.com/mastra-ai/mastra/commit/1d677d5f99d7db403f7828585e8c25f299f72628), [`9e1dad8`](https://github.com/mastra-ai/mastra/commit/9e1dad8f7b1cab2bb7ade90e5b7561f24577b88a), [`2f43145`](https://github.com/mastra-ai/mastra/commit/2f4314504c03cbba280414ac81ba3197448ee6b0), [`4e35a56`](https://github.com/mastra-ai/mastra/commit/4e35a56cdf8d74a5ff6d5eda01f2c1deaf6cc7be), [`d94b8e1`](https://github.com/mastra-ai/mastra/commit/d94b8e1cee67416d518a8c30099040061bef6a1c), [`93e28ec`](https://github.com/mastra-ai/mastra/commit/93e28ecce9031c02397e0ae8406593e5c7a95883), [`729dab4`](https://github.com/mastra-ai/mastra/commit/729dab408faccfaef0cbb048e5a4338f9172847e), [`484003d`](https://github.com/mastra-ai/mastra/commit/484003d33ff59330c86b19863e4a38732d7e4155), [`3de0188`](https://github.com/mastra-ai/mastra/commit/3de0188bfaf9a9c09c95fe322b53838cf52c70b6), [`34d34d8`](https://github.com/mastra-ai/mastra/commit/34d34d8c811df512fef4dd5459f79b7821be1866), [`b582f7f`](https://github.com/mastra-ai/mastra/commit/b582f7fa2f9c1f87d19efc63d344fbe5dda2608c), [`933d291`](https://github.com/mastra-ai/mastra/commit/933d291146b789c19442ad206f94da3e4be90c64), [`a1cb98d`](https://github.com/mastra-ai/mastra/commit/a1cb98d11990b560b98482292a1f34aa1a2d9092), [`598ad82`](https://github.com/mastra-ai/mastra/commit/598ad82d41c41389a686338a1d0e50b7400e1938), [`1fd6aad`](https://github.com/mastra-ai/mastra/commit/1fd6aad1ea4a9d32f65efa832307c35e981a4c0a)]:
123
+ - @mastra/core@1.56.0
124
+
3
125
  ## 1.5.0-alpha.2
4
126
 
5
127
  ### 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-alpha.2"
6
+ version: "1.6.0-alpha.0"
7
7
  ---
8
8
 
9
9
  ## When to use
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.5.0-alpha.2",
2
+ "version": "1.6.0-alpha.0",
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,7 +6735,7 @@ 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
6741
  /** Resolves the `include` clause: pinned messages plus their before/after windows. */