@mastra/spanner 1.4.0 → 1.5.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 +64 -0
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/reference-storage-spanner.md +8 -8
- package/dist/index.cjs +193 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +194 -8
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/datasets/index.d.ts.map +1 -1
- package/dist/storage/domains/experiments/index.d.ts.map +1 -1
- package/dist/storage/domains/workflow-definitions/index.d.ts +22 -0
- package/dist/storage/domains/workflow-definitions/index.d.ts.map +1 -0
- package/dist/storage/index.d.ts +3 -2
- package/dist/storage/index.d.ts.map +1 -1
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,69 @@
|
|
|
1
1
|
# @mastra/spanner
|
|
2
2
|
|
|
3
|
+
## 1.5.0-alpha.1
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Stored workflow definitions now persist across restarts on every major database backend. ([#20471](https://github.com/mastra-ai/mastra/pull/20471))
|
|
8
|
+
|
|
9
|
+
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.
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
const workflowDefinitions = await storage.getStore('workflowDefinitions');
|
|
13
|
+
if (!workflowDefinitions) {
|
|
14
|
+
throw new Error('This storage adapter does not support the workflowDefinitions domain');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
await workflowDefinitions.upsert({
|
|
18
|
+
id: 'greeting-workflow',
|
|
19
|
+
inputSchema: { type: 'object', properties: { name: { type: 'string' } }, required: ['name'] },
|
|
20
|
+
outputSchema: { type: 'object', properties: { text: { type: 'string' } }, required: ['text'] },
|
|
21
|
+
graph: [{ type: 'agent', id: 'greet', agentId: 'greeter-agent' }],
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const { definitions, total } = await workflowDefinitions.list({ status: 'active' });
|
|
25
|
+
const definition = await workflowDefinitions.get('greeting-workflow');
|
|
26
|
+
await workflowDefinitions.delete('greeting-workflow');
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Each adapter now ships a `WorkflowDefinitions*` domain that:
|
|
30
|
+
|
|
31
|
+
- Creates the shared `mastra_workflow_definitions` table (or Mongo collection) from `WORKFLOW_DEFINITIONS_SCHEMA` during `init()`, plus a default index on `status`.
|
|
32
|
+
- 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.
|
|
33
|
+
- 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.
|
|
34
|
+
- 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.
|
|
35
|
+
|
|
36
|
+
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.
|
|
37
|
+
|
|
38
|
+
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.
|
|
39
|
+
|
|
40
|
+
`@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).
|
|
41
|
+
|
|
42
|
+
### Patch Changes
|
|
43
|
+
|
|
44
|
+
- Updated dependencies [[`4844167`](https://github.com/mastra-ai/mastra/commit/4844167cff2d5ec5004e94edd34970833040fa3f), [`5faf93f`](https://github.com/mastra-ai/mastra/commit/5faf93f03e19daea394b9e2a923f2e4f833407f2), [`80ad891`](https://github.com/mastra-ai/mastra/commit/80ad891f8cd10379aa5b5af7510c763783b2ab56), [`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)]:
|
|
45
|
+
- @mastra/core@1.56.0-alpha.4
|
|
46
|
+
|
|
47
|
+
## 1.5.0-alpha.0
|
|
48
|
+
|
|
49
|
+
### Minor Changes
|
|
50
|
+
|
|
51
|
+
- Added persistence for dataset item undeclared tool policies. ([#19643](https://github.com/mastra-ai/mastra/pull/19643))
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
await dataset.addItem({
|
|
55
|
+
input: 'What is the weather?',
|
|
56
|
+
unmockedToolPolicy: 'deny',
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Patch Changes
|
|
61
|
+
|
|
62
|
+
- 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))
|
|
63
|
+
|
|
64
|
+
- Updated dependencies [[`c5e56ff`](https://github.com/mastra-ai/mastra/commit/c5e56ff3bcabdf062708f2d48744fec304df6792), [`4e35a56`](https://github.com/mastra-ai/mastra/commit/4e35a56cdf8d74a5ff6d5eda01f2c1deaf6cc7be)]:
|
|
65
|
+
- @mastra/core@1.56.0-alpha.1
|
|
66
|
+
|
|
3
67
|
## 1.4.0
|
|
4
68
|
|
|
5
69
|
### Minor Changes
|
package/dist/docs/SKILL.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# Google Cloud Spanner storage
|
|
4
4
|
|
|
5
|
-
The Google Cloud Spanner storage implementation provides a horizontally
|
|
5
|
+
The Google Cloud Spanner storage implementation provides a horizontally high-capacity, strongly consistent storage backend for Mastra. It targets the GoogleSQL dialect of Cloud Spanner.
|
|
6
6
|
|
|
7
7
|
## Installation
|
|
8
8
|
|
|
@@ -133,14 +133,14 @@ The storage adapter creates the following tables, all using the GoogleSQL dialec
|
|
|
133
133
|
|
|
134
134
|
Tables are created with `STRING(MAX)` for text and JSON payloads, `INT64`, `FLOAT64`, `BOOL`, and `TIMESTAMP`.
|
|
135
135
|
|
|
136
|
-
|
|
136
|
+
The following tables carry Spanner-specific `STORED` generated columns that the adapter populates from JSON payloads so common filters can use a regular secondary index instead of a `JSON_VALUE` scan:
|
|
137
137
|
|
|
138
|
-
- `mastra_workflow_snapshot.snapshotStatus
|
|
139
|
-
- `mastra_schedules.target_workflow_id
|
|
138
|
+
- `mastra_workflow_snapshot.snapshotStatus`: Extracts `$.status` from `snapshot`. Backs `listWorkflowRuns({ status })`.
|
|
139
|
+
- `mastra_schedules.target_workflow_id`: Extracts `$.workflowId` from `target`. Backs `listSchedules({ workflowId })`.
|
|
140
140
|
|
|
141
141
|
Both are added via `ALTER TABLE ... ADD COLUMN IF NOT EXISTS` during `init()` and skipped under `initMode: 'validate'` (where the schema is owned externally). When the column is absent, the adapter falls back to a `JSON_VALUE` filter at runtime.
|
|
142
142
|
|
|
143
|
-
The adapter doesn't create or use
|
|
143
|
+
The adapter doesn't create or use schemas. Use a dedicated database for isolation.
|
|
144
144
|
|
|
145
145
|
### Initialization
|
|
146
146
|
|
|
@@ -184,11 +184,11 @@ const thread = await memory?.getThreadById({ threadId: '...' })
|
|
|
184
184
|
A few behaviors differ from other relational adapters:
|
|
185
185
|
|
|
186
186
|
- Upserts use `INSERT OR UPDATE`. Spanner doesn't provide a `RETURNING` clause for upserts, so callers needing the post-write state must read it back.
|
|
187
|
-
- No `TRUNCATE` exists
|
|
187
|
+
- No `TRUNCATE` exists. `dangerouslyClearAll()` issues `DELETE WHERE TRUE`.
|
|
188
188
|
- Identifiers are quoted with backticks.
|
|
189
189
|
- DDL is applied through `database.updateSchema(...)`, which is asynchronous (long-running operation).
|
|
190
190
|
- `NULLS FIRST/LAST` isn't supported. Ordering with NULL handling is emulated through an `IS NULL` ordering key.
|
|
191
|
-
- JSON containment isn't supported natively. `listTraces` `metadata` and `scope` filters compile to per-key `JSON_VALUE(...) = @v` equality checks, and `tags` filters compile to `EXISTS` over `JSON_QUERY_ARRAY(...)`. This differs from Postgres' `@>` containment operator (which can match nested structure in a single index scan)
|
|
191
|
+
- JSON containment isn't supported natively. `listTraces` `metadata` and `scope` filters compile to per-key `JSON_VALUE(...) = @v` equality checks, and `tags` filters compile to `EXISTS` over `JSON_QUERY_ARRAY(...)`. This differs from Postgres' `@>` containment operator (which can match nested structure in a single index scan): most one-shot lookups still work but deeply nested structural matches aren't expressible.
|
|
192
192
|
|
|
193
193
|
### Direct database access
|
|
194
194
|
|
|
@@ -217,4 +217,4 @@ gcloud spanner instances create test-instance --config=emulator-config --nodes=1
|
|
|
217
217
|
gcloud spanner databases create test-db --instance=test-instance
|
|
218
218
|
```
|
|
219
219
|
|
|
220
|
-
Then connect with the same env var set in your Node.js process
|
|
220
|
+
Then connect with the same env var set in your Node.js process. The `@google-cloud/spanner` client detects the emulator automatically.
|
package/dist/index.cjs
CHANGED
|
@@ -2788,6 +2788,7 @@ function rowToItem(row) {
|
|
|
2788
2788
|
groundTruth: t.groundTruth ?? void 0,
|
|
2789
2789
|
expectedTrajectory: t.expectedTrajectory ?? void 0,
|
|
2790
2790
|
toolMocks: t.toolMocks ?? void 0,
|
|
2791
|
+
unmockedToolPolicy: t.unmockedToolPolicy ?? void 0,
|
|
2791
2792
|
requestContext: t.requestContext ?? void 0,
|
|
2792
2793
|
metadata: t.metadata ?? void 0,
|
|
2793
2794
|
source: t.source ?? void 0,
|
|
@@ -2885,7 +2886,8 @@ var DatasetsSpanner = class DatasetsSpanner extends _mastra_core_storage.Dataset
|
|
|
2885
2886
|
ifNotExists: [
|
|
2886
2887
|
"organizationId",
|
|
2887
2888
|
"projectId",
|
|
2888
|
-
"externalId"
|
|
2889
|
+
"externalId",
|
|
2890
|
+
"unmockedToolPolicy"
|
|
2889
2891
|
]
|
|
2890
2892
|
});
|
|
2891
2893
|
await this.createDefaultIndexes();
|
|
@@ -3350,6 +3352,7 @@ var DatasetsSpanner = class DatasetsSpanner extends _mastra_core_storage.Dataset
|
|
|
3350
3352
|
groundTruth: args.groundTruth ?? null,
|
|
3351
3353
|
expectedTrajectory: args.expectedTrajectory ?? null,
|
|
3352
3354
|
toolMocks: args.toolMocks ?? null,
|
|
3355
|
+
unmockedToolPolicy: args.unmockedToolPolicy ?? null,
|
|
3353
3356
|
requestContext: args.requestContext ?? null,
|
|
3354
3357
|
metadata: args.metadata ?? null,
|
|
3355
3358
|
source: args.source ?? null,
|
|
@@ -3370,6 +3373,7 @@ var DatasetsSpanner = class DatasetsSpanner extends _mastra_core_storage.Dataset
|
|
|
3370
3373
|
groundTruth: args.groundTruth,
|
|
3371
3374
|
expectedTrajectory: args.expectedTrajectory,
|
|
3372
3375
|
toolMocks: args.toolMocks,
|
|
3376
|
+
unmockedToolPolicy: args.unmockedToolPolicy,
|
|
3373
3377
|
requestContext: args.requestContext,
|
|
3374
3378
|
metadata: args.metadata,
|
|
3375
3379
|
source: args.source,
|
|
@@ -3419,6 +3423,7 @@ var DatasetsSpanner = class DatasetsSpanner extends _mastra_core_storage.Dataset
|
|
|
3419
3423
|
groundTruth: args.groundTruth !== void 0 ? args.groundTruth : existing.groundTruth,
|
|
3420
3424
|
expectedTrajectory: args.expectedTrajectory !== void 0 ? args.expectedTrajectory : existing.expectedTrajectory,
|
|
3421
3425
|
toolMocks: args.toolMocks !== void 0 ? args.toolMocks : existing.toolMocks,
|
|
3426
|
+
unmockedToolPolicy: args.unmockedToolPolicy !== void 0 ? args.unmockedToolPolicy : existing.unmockedToolPolicy,
|
|
3422
3427
|
requestContext: args.requestContext !== void 0 ? args.requestContext : existing.requestContext,
|
|
3423
3428
|
metadata: args.metadata !== void 0 ? args.metadata : existing.metadata,
|
|
3424
3429
|
source: args.source !== void 0 ? args.source : existing.source
|
|
@@ -3444,6 +3449,7 @@ var DatasetsSpanner = class DatasetsSpanner extends _mastra_core_storage.Dataset
|
|
|
3444
3449
|
groundTruth: merged.groundTruth ?? null,
|
|
3445
3450
|
expectedTrajectory: merged.expectedTrajectory ?? null,
|
|
3446
3451
|
toolMocks: merged.toolMocks ?? null,
|
|
3452
|
+
unmockedToolPolicy: merged.unmockedToolPolicy ?? null,
|
|
3447
3453
|
requestContext: merged.requestContext ?? null,
|
|
3448
3454
|
metadata: merged.metadata ?? null,
|
|
3449
3455
|
source: merged.source ?? null,
|
|
@@ -3465,6 +3471,7 @@ var DatasetsSpanner = class DatasetsSpanner extends _mastra_core_storage.Dataset
|
|
|
3465
3471
|
groundTruth: merged.groundTruth,
|
|
3466
3472
|
expectedTrajectory: merged.expectedTrajectory,
|
|
3467
3473
|
toolMocks: merged.toolMocks,
|
|
3474
|
+
unmockedToolPolicy: merged.unmockedToolPolicy,
|
|
3468
3475
|
requestContext: merged.requestContext,
|
|
3469
3476
|
metadata: merged.metadata,
|
|
3470
3477
|
source: merged.source,
|
|
@@ -3523,6 +3530,7 @@ var DatasetsSpanner = class DatasetsSpanner extends _mastra_core_storage.Dataset
|
|
|
3523
3530
|
groundTruth: existing.groundTruth ?? null,
|
|
3524
3531
|
expectedTrajectory: existing.expectedTrajectory ?? null,
|
|
3525
3532
|
toolMocks: existing.toolMocks ?? null,
|
|
3533
|
+
unmockedToolPolicy: existing.unmockedToolPolicy ?? null,
|
|
3526
3534
|
requestContext: existing.requestContext ?? null,
|
|
3527
3535
|
metadata: existing.metadata ?? null,
|
|
3528
3536
|
source: existing.source ?? null,
|
|
@@ -3839,6 +3847,7 @@ var DatasetsSpanner = class DatasetsSpanner extends _mastra_core_storage.Dataset
|
|
|
3839
3847
|
groundTruth: insert.item.groundTruth,
|
|
3840
3848
|
expectedTrajectory: insert.item.expectedTrajectory,
|
|
3841
3849
|
toolMocks: insert.item.toolMocks,
|
|
3850
|
+
unmockedToolPolicy: insert.item.unmockedToolPolicy,
|
|
3842
3851
|
requestContext: insert.item.requestContext,
|
|
3843
3852
|
metadata: insert.item.metadata,
|
|
3844
3853
|
source: insert.item.source,
|
|
@@ -3907,6 +3916,7 @@ var DatasetsSpanner = class DatasetsSpanner extends _mastra_core_storage.Dataset
|
|
|
3907
3916
|
groundTruth: existing.groundTruth ?? null,
|
|
3908
3917
|
expectedTrajectory: existing.expectedTrajectory ?? null,
|
|
3909
3918
|
toolMocks: existing.toolMocks ?? null,
|
|
3919
|
+
unmockedToolPolicy: existing.unmockedToolPolicy ?? null,
|
|
3910
3920
|
requestContext: existing.requestContext ?? null,
|
|
3911
3921
|
metadata: existing.metadata ?? null,
|
|
3912
3922
|
source: existing.source ?? null,
|
|
@@ -3991,6 +4001,7 @@ function rowToExperimentResult(row) {
|
|
|
3991
4001
|
traceId: t.traceId ?? null,
|
|
3992
4002
|
status: t.status ?? null,
|
|
3993
4003
|
tags: t.tags ?? null,
|
|
4004
|
+
comment: t.comment ?? null,
|
|
3994
4005
|
toolMockReport: t.toolMockReport ?? null,
|
|
3995
4006
|
createdAt: toDate(t.createdAt)
|
|
3996
4007
|
};
|
|
@@ -4035,7 +4046,11 @@ var ExperimentsSpanner = class ExperimentsSpanner extends _mastra_core_storage.E
|
|
|
4035
4046
|
await this.db.alterTable({
|
|
4036
4047
|
tableName: _mastra_core_storage.TABLE_EXPERIMENT_RESULTS,
|
|
4037
4048
|
schema: _mastra_core_storage.TABLE_SCHEMAS[_mastra_core_storage.TABLE_EXPERIMENT_RESULTS],
|
|
4038
|
-
ifNotExists: [
|
|
4049
|
+
ifNotExists: [
|
|
4050
|
+
"comment",
|
|
4051
|
+
"organizationId",
|
|
4052
|
+
"projectId"
|
|
4053
|
+
]
|
|
4039
4054
|
});
|
|
4040
4055
|
await this.createDefaultIndexes();
|
|
4041
4056
|
await this.createCustomIndexes();
|
|
@@ -4428,7 +4443,7 @@ var ExperimentsSpanner = class ExperimentsSpanner extends _mastra_core_storage.E
|
|
|
4428
4443
|
}
|
|
4429
4444
|
async updateExperimentResult(input) {
|
|
4430
4445
|
try {
|
|
4431
|
-
if (input.status === void 0 && input.tags === void 0) {
|
|
4446
|
+
if (input.status === void 0 && input.tags === void 0 && input.comment === void 0) {
|
|
4432
4447
|
const existing = await this.getExperimentResultById({ id: input.id });
|
|
4433
4448
|
if (!existing || input.experimentId !== void 0 && existing.experimentId !== input.experimentId) throw new _mastra_core_error.MastraError({
|
|
4434
4449
|
id: (0, _mastra_core_storage.createStorageErrorId)("SPANNER", "UPDATE_EXPERIMENT_RESULT", "NOT_FOUND"),
|
|
@@ -4452,6 +4467,11 @@ var ExperimentsSpanner = class ExperimentsSpanner extends _mastra_core_storage.E
|
|
|
4452
4467
|
params.tags = input.tags === null ? null : JSON.stringify(input.tags);
|
|
4453
4468
|
types.tags = "json";
|
|
4454
4469
|
}
|
|
4470
|
+
if (input.comment !== void 0) {
|
|
4471
|
+
setClauses.push(`${quoteIdent("comment", "column name")} = @comment`);
|
|
4472
|
+
params.comment = input.comment;
|
|
4473
|
+
if (input.comment === null) types.comment = "string";
|
|
4474
|
+
}
|
|
4455
4475
|
const whereClauses = [`${quoteIdent("id", "column name")} = @id`];
|
|
4456
4476
|
if (input.experimentId !== void 0) {
|
|
4457
4477
|
whereClauses.push(`${quoteIdent("experimentId", "column name")} = @experimentId`);
|
|
@@ -11481,6 +11501,169 @@ var SkillsSpanner = class SkillsSpanner extends _mastra_core_storage.SkillsStora
|
|
|
11481
11501
|
}
|
|
11482
11502
|
};
|
|
11483
11503
|
//#endregion
|
|
11504
|
+
//#region src/storage/domains/workflow-definitions/index.ts
|
|
11505
|
+
function rowToDefinition(row) {
|
|
11506
|
+
const parsed = transformFromSpannerRow({
|
|
11507
|
+
tableName: _mastra_core_storage.TABLE_WORKFLOW_DEFINITIONS,
|
|
11508
|
+
row
|
|
11509
|
+
});
|
|
11510
|
+
if (parsed.inputSchema == null || parsed.outputSchema == null || parsed.graph == null) throw new Error(`Workflow definition row "${String(parsed.id)}" is missing required JSON columns.`);
|
|
11511
|
+
const def = {
|
|
11512
|
+
id: String(parsed.id),
|
|
11513
|
+
inputSchema: parsed.inputSchema,
|
|
11514
|
+
outputSchema: parsed.outputSchema,
|
|
11515
|
+
graph: parsed.graph,
|
|
11516
|
+
status: parsed.status,
|
|
11517
|
+
source: parsed.source,
|
|
11518
|
+
createdAt: parsed.createdAt instanceof Date ? parsed.createdAt : new Date(parsed.createdAt),
|
|
11519
|
+
updatedAt: parsed.updatedAt instanceof Date ? parsed.updatedAt : new Date(parsed.updatedAt)
|
|
11520
|
+
};
|
|
11521
|
+
if (parsed.description != null) def.description = parsed.description;
|
|
11522
|
+
if (parsed.metadata != null) def.metadata = parsed.metadata;
|
|
11523
|
+
if (parsed.stateSchema != null) def.stateSchema = parsed.stateSchema;
|
|
11524
|
+
if (parsed.requestContextSchema != null) def.requestContextSchema = parsed.requestContextSchema;
|
|
11525
|
+
if (parsed.authorId != null) def.authorId = parsed.authorId;
|
|
11526
|
+
return def;
|
|
11527
|
+
}
|
|
11528
|
+
var WorkflowDefinitionsSpanner = class WorkflowDefinitionsSpanner extends _mastra_core_storage.WorkflowDefinitionsStorage {
|
|
11529
|
+
database;
|
|
11530
|
+
db;
|
|
11531
|
+
skipDefaultIndexes;
|
|
11532
|
+
indexes;
|
|
11533
|
+
static MANAGED_TABLES = [_mastra_core_storage.TABLE_WORKFLOW_DEFINITIONS];
|
|
11534
|
+
constructor(config) {
|
|
11535
|
+
super();
|
|
11536
|
+
const { database, indexes, skipDefaultIndexes, initMode } = resolveSpannerConfig(config);
|
|
11537
|
+
this.database = database;
|
|
11538
|
+
this.db = new SpannerDB({
|
|
11539
|
+
database,
|
|
11540
|
+
skipDefaultIndexes,
|
|
11541
|
+
initMode
|
|
11542
|
+
});
|
|
11543
|
+
this.skipDefaultIndexes = skipDefaultIndexes;
|
|
11544
|
+
this.indexes = indexes?.filter((idx) => WorkflowDefinitionsSpanner.MANAGED_TABLES.includes(idx.table));
|
|
11545
|
+
}
|
|
11546
|
+
async init() {
|
|
11547
|
+
await this.db.createTable({
|
|
11548
|
+
tableName: _mastra_core_storage.TABLE_WORKFLOW_DEFINITIONS,
|
|
11549
|
+
schema: _mastra_core_storage.WORKFLOW_DEFINITIONS_SCHEMA
|
|
11550
|
+
});
|
|
11551
|
+
await this.createDefaultIndexes();
|
|
11552
|
+
await this.createCustomIndexes();
|
|
11553
|
+
}
|
|
11554
|
+
getDefaultIndexDefinitions() {
|
|
11555
|
+
return [{
|
|
11556
|
+
name: "mastra_workflow_definitions_status_idx",
|
|
11557
|
+
table: _mastra_core_storage.TABLE_WORKFLOW_DEFINITIONS,
|
|
11558
|
+
columns: ["status"]
|
|
11559
|
+
}];
|
|
11560
|
+
}
|
|
11561
|
+
async createDefaultIndexes() {
|
|
11562
|
+
if (this.skipDefaultIndexes) return;
|
|
11563
|
+
await this.db.createIndexes(this.getDefaultIndexDefinitions());
|
|
11564
|
+
}
|
|
11565
|
+
async createCustomIndexes() {
|
|
11566
|
+
if (!this.indexes || this.indexes.length === 0) return;
|
|
11567
|
+
await this.db.createIndexes(this.indexes);
|
|
11568
|
+
}
|
|
11569
|
+
async dangerouslyClearAll() {
|
|
11570
|
+
await this.db.clearTable({ tableName: _mastra_core_storage.TABLE_WORKFLOW_DEFINITIONS });
|
|
11571
|
+
}
|
|
11572
|
+
async upsert(input) {
|
|
11573
|
+
const now = /* @__PURE__ */ new Date();
|
|
11574
|
+
if (!await this.get(input.id)) {
|
|
11575
|
+
if (!("inputSchema" in input) || input.inputSchema === void 0) throw new Error(`Cannot create workflow definition "${input.id}": inputSchema is required.`);
|
|
11576
|
+
if (!("outputSchema" in input) || input.outputSchema === void 0) throw new Error(`Cannot create workflow definition "${input.id}": outputSchema is required.`);
|
|
11577
|
+
if (!("graph" in input) || input.graph === void 0) throw new Error(`Cannot create workflow definition "${input.id}": graph is required.`);
|
|
11578
|
+
const record = {
|
|
11579
|
+
id: input.id,
|
|
11580
|
+
description: input.description ?? null,
|
|
11581
|
+
metadata: input.metadata ?? null,
|
|
11582
|
+
inputSchema: input.inputSchema,
|
|
11583
|
+
outputSchema: input.outputSchema,
|
|
11584
|
+
stateSchema: input.stateSchema ?? null,
|
|
11585
|
+
requestContextSchema: input.requestContextSchema ?? null,
|
|
11586
|
+
graph: input.graph,
|
|
11587
|
+
status: "active",
|
|
11588
|
+
source: "storage",
|
|
11589
|
+
authorId: "authorId" in input ? input.authorId ?? null : null,
|
|
11590
|
+
createdAt: now,
|
|
11591
|
+
updatedAt: now
|
|
11592
|
+
};
|
|
11593
|
+
try {
|
|
11594
|
+
await this.db.insert({
|
|
11595
|
+
tableName: _mastra_core_storage.TABLE_WORKFLOW_DEFINITIONS,
|
|
11596
|
+
record
|
|
11597
|
+
});
|
|
11598
|
+
} catch (error) {
|
|
11599
|
+
if (!await this.get(input.id)) throw error;
|
|
11600
|
+
return this.applyUpdate(input, now);
|
|
11601
|
+
}
|
|
11602
|
+
const created = await this.get(input.id);
|
|
11603
|
+
if (!created) throw new Error(`Failed to persist workflow definition "${input.id}".`);
|
|
11604
|
+
return created;
|
|
11605
|
+
}
|
|
11606
|
+
return this.applyUpdate(input, now);
|
|
11607
|
+
}
|
|
11608
|
+
async applyUpdate(input, now) {
|
|
11609
|
+
const data = { updatedAt: now };
|
|
11610
|
+
if ("description" in input && input.description !== void 0) data.description = input.description;
|
|
11611
|
+
if ("metadata" in input && input.metadata !== void 0) data.metadata = input.metadata;
|
|
11612
|
+
if ("inputSchema" in input && input.inputSchema !== void 0) data.inputSchema = input.inputSchema;
|
|
11613
|
+
if ("outputSchema" in input && input.outputSchema !== void 0) data.outputSchema = input.outputSchema;
|
|
11614
|
+
if ("stateSchema" in input && input.stateSchema !== void 0) data.stateSchema = input.stateSchema;
|
|
11615
|
+
if ("requestContextSchema" in input && input.requestContextSchema !== void 0) data.requestContextSchema = input.requestContextSchema;
|
|
11616
|
+
if ("graph" in input && input.graph !== void 0) data.graph = input.graph;
|
|
11617
|
+
if ("status" in input && input.status !== void 0) data.status = input.status;
|
|
11618
|
+
if ("authorId" in input && input.authorId !== void 0) data.authorId = input.authorId;
|
|
11619
|
+
await this.db.update({
|
|
11620
|
+
tableName: _mastra_core_storage.TABLE_WORKFLOW_DEFINITIONS,
|
|
11621
|
+
keys: { id: input.id },
|
|
11622
|
+
data
|
|
11623
|
+
});
|
|
11624
|
+
const updated = await this.get(input.id);
|
|
11625
|
+
if (!updated) throw new Error(`Failed to update workflow definition "${input.id}".`);
|
|
11626
|
+
return updated;
|
|
11627
|
+
}
|
|
11628
|
+
async get(id) {
|
|
11629
|
+
const row = await this.db.load({
|
|
11630
|
+
tableName: _mastra_core_storage.TABLE_WORKFLOW_DEFINITIONS,
|
|
11631
|
+
keys: { id }
|
|
11632
|
+
});
|
|
11633
|
+
return row ? rowToDefinition(row) : null;
|
|
11634
|
+
}
|
|
11635
|
+
async list(args) {
|
|
11636
|
+
const params = {};
|
|
11637
|
+
const conditions = [];
|
|
11638
|
+
if (args?.status) {
|
|
11639
|
+
params.status = args.status;
|
|
11640
|
+
conditions.push(`${quoteIdent("status", "column name")} = @status`);
|
|
11641
|
+
}
|
|
11642
|
+
if (args?.authorId !== void 0) {
|
|
11643
|
+
params.authorId = args.authorId;
|
|
11644
|
+
conditions.push(`${quoteIdent("authorId", "column name")} = @authorId`);
|
|
11645
|
+
}
|
|
11646
|
+
const where = conditions.length ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
11647
|
+
const sql = `SELECT * FROM ${quoteIdent(_mastra_core_storage.TABLE_WORKFLOW_DEFINITIONS, "table name")} ${where} ORDER BY ${quoteIdent("updatedAt", "column name")} DESC`;
|
|
11648
|
+
const [rows] = await this.database.run({
|
|
11649
|
+
sql,
|
|
11650
|
+
params,
|
|
11651
|
+
json: true
|
|
11652
|
+
});
|
|
11653
|
+
const definitions = rows.map(rowToDefinition);
|
|
11654
|
+
return {
|
|
11655
|
+
definitions,
|
|
11656
|
+
total: definitions.length
|
|
11657
|
+
};
|
|
11658
|
+
}
|
|
11659
|
+
async delete(id) {
|
|
11660
|
+
await this.db.runDml({
|
|
11661
|
+
sql: `DELETE FROM ${quoteIdent(_mastra_core_storage.TABLE_WORKFLOW_DEFINITIONS, "table name")} WHERE id = @id`,
|
|
11662
|
+
params: { id }
|
|
11663
|
+
});
|
|
11664
|
+
}
|
|
11665
|
+
};
|
|
11666
|
+
//#endregion
|
|
11484
11667
|
//#region src/storage/domains/workflows/index.ts
|
|
11485
11668
|
/**
|
|
11486
11669
|
* Spanner-backed storage for workflow run snapshots, including persistence,
|
|
@@ -12649,7 +12832,8 @@ const SPANNER_DOMAIN_KEYS = [
|
|
|
12649
12832
|
"datasets",
|
|
12650
12833
|
"experiments",
|
|
12651
12834
|
"favorites",
|
|
12652
|
-
"workspaces"
|
|
12835
|
+
"workspaces",
|
|
12836
|
+
"workflowDefinitions"
|
|
12653
12837
|
];
|
|
12654
12838
|
const isPreConfiguredDatabase = (config) => "database" in config && !!config.database;
|
|
12655
12839
|
/**
|
|
@@ -12737,7 +12921,8 @@ var SpannerStore = class extends _mastra_core_storage.MastraCompositeStore {
|
|
|
12737
12921
|
...wants("datasets") && { datasets: new DatasetsSpanner(domainConfig) },
|
|
12738
12922
|
...wants("experiments") && { experiments: new ExperimentsSpanner(domainConfig) },
|
|
12739
12923
|
...wants("favorites") && { favorites: new FavoritesSpanner(domainConfig) },
|
|
12740
|
-
...wants("workspaces") && { workspaces: new WorkspacesSpanner(domainConfig) }
|
|
12924
|
+
...wants("workspaces") && { workspaces: new WorkspacesSpanner(domainConfig) },
|
|
12925
|
+
...wants("workflowDefinitions") && { workflowDefinitions: new WorkflowDefinitionsSpanner(domainConfig) }
|
|
12741
12926
|
};
|
|
12742
12927
|
} catch (e) {
|
|
12743
12928
|
throw new _mastra_core_error.MastraError({
|
|
@@ -12793,7 +12978,8 @@ var SpannerStore = class extends _mastra_core_storage.MastraCompositeStore {
|
|
|
12793
12978
|
"datasets",
|
|
12794
12979
|
"experiments",
|
|
12795
12980
|
"workspaces",
|
|
12796
|
-
"favorites"
|
|
12981
|
+
"favorites",
|
|
12982
|
+
"workflowDefinitions"
|
|
12797
12983
|
]) {
|
|
12798
12984
|
const store = this.stores?.[key];
|
|
12799
12985
|
if (store) await store.init();
|
|
@@ -12843,6 +13029,7 @@ exports.ScorerDefinitionsSpanner = ScorerDefinitionsSpanner;
|
|
|
12843
13029
|
exports.ScoresSpanner = ScoresSpanner;
|
|
12844
13030
|
exports.SkillsSpanner = SkillsSpanner;
|
|
12845
13031
|
exports.SpannerStore = SpannerStore;
|
|
13032
|
+
exports.WorkflowDefinitionsSpanner = WorkflowDefinitionsSpanner;
|
|
12846
13033
|
exports.WorkflowsSpanner = WorkflowsSpanner;
|
|
12847
13034
|
exports.WorkspacesSpanner = WorkspacesSpanner;
|
|
12848
13035
|
|