@mastra/pg 1.21.1-alpha.0 → 1.21.1-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 +42 -0
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/reference-rag-metadata-filters.md +16 -8
- package/dist/docs/references/reference-rag-retrieval.md +113 -5
- package/dist/index.cjs +110 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +110 -13
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/experiments/index.d.ts +2 -1
- package/dist/storage/domains/experiments/index.d.ts.map +1 -1
- package/dist/storage/domains/scores/index.d.ts.map +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,47 @@
|
|
|
1
1
|
# @mastra/pg
|
|
2
2
|
|
|
3
|
+
## 1.21.1-alpha.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Added HTTP endpoints for caller-driven experiments: `POST /datasets/:datasetId/experiments` now accepts `start: false` to create an experiment without spawning the runner (with an optional target and run-level `scorerIds`), and new routes `POST /datasets/:datasetId/experiments/:experimentId/items/:itemId/run`, `POST /datasets/:datasetId/experiments/:experimentId/results`, and `POST /datasets/:datasetId/experiments/:experimentId/finalize` let external orchestrators run one item server-side, submit externally computed per-item results (idempotent upsert on retries), and finalize the run with server-computed counts. ([#21888](https://github.com/mastra-ai/mastra/pull/21888))
|
|
8
|
+
|
|
9
|
+
- Added `createDatasetExperiment()`, `runExperimentItem()`, `submitExperimentResult()`, and `finalizeExperiment()` methods so a caller-owned orchestrator (for example Temporal) can drive an experiment loop while Mastra either executes each item server-side or ingests externally computed results. ([#21888](https://github.com/mastra-ai/mastra/pull/21888))
|
|
10
|
+
|
|
11
|
+
- Added `upsertExperimentResult()` to the experiments storage domain plus an `attempt` column on experiment results and a nullable target with an optional `scorerIds` column on experiments, enabling retry-safe result writes for caller-driven experiments (retried submissions with the same `(experimentId, itemId, attempt)` key converge on a single row). `saveScore()` now accepts an optional caller-supplied `id` and upserts on it, so retried experiment submissions replace their previous score rows (latest wins) instead of accumulating duplicates. ([#21888](https://github.com/mastra-ai/mastra/pull/21888))
|
|
12
|
+
|
|
13
|
+
- Added caller-driven experiments so an external orchestrator (for example Temporal workers) can own the experiment loop while Mastra stays the system of record. ([#21888](https://github.com/mastra-ai/mastra/pull/21888))
|
|
14
|
+
|
|
15
|
+
Create an experiment with `dataset.createExperiment()` (idempotent when you pass your own id). With a target, Mastra runs each item for you: call `dataset.runExperimentItem()` per item and Mastra executes the registered agent or workflow, resolves scorers (experiment `scorers`, falling back to item `scorerIds`, then dataset `scorerIds`), and upserts the result. Without a target, run everything yourself and report per-item results with `dataset.submitExperimentResult()` (upsert semantics on `(experimentId, itemId, attempt)` so retried workers converge on a single row). Either way, close the run with `dataset.finalizeExperiment()` and Mastra computes per-item succeeded/failed/skipped counts from the persisted rows. Results go into the same storage as native runs, so Studio views, comparisons, and review summaries work unchanged.
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
// Caller drives the loop, Mastra runs each item
|
|
19
|
+
const { experimentId } = await dataset.createExperiment({
|
|
20
|
+
id: workflowRunId,
|
|
21
|
+
targetType: 'agent',
|
|
22
|
+
targetId: 'support-agent',
|
|
23
|
+
scorers: ['accuracy'],
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
await dataset.runExperimentItem({ experimentId, itemId });
|
|
27
|
+
|
|
28
|
+
// Or: caller runs everything, Mastra ingests results
|
|
29
|
+
const ingest = await dataset.createExperiment({ id: workflowRunId });
|
|
30
|
+
await dataset.submitExperimentResult({
|
|
31
|
+
experimentId: ingest.experimentId,
|
|
32
|
+
itemId,
|
|
33
|
+
output,
|
|
34
|
+
scores: [{ scorerId: 'accuracy', score: 0.92 }],
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const experiment = await dataset.finalizeExperiment({ experimentId });
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
- Fixed versioned dataset item lookups to return the item visible in the requested dataset snapshot. ([#21979](https://github.com/mastra-ai/mastra/pull/21979))
|
|
41
|
+
|
|
42
|
+
- Updated dependencies [[`9267e9b`](https://github.com/mastra-ai/mastra/commit/9267e9b3d9c2fcf16936050495a787054c2431ab), [`acc3471`](https://github.com/mastra-ai/mastra/commit/acc3471de5f3fde8027ee4e355af292b2bc1bc30), [`b6a771e`](https://github.com/mastra-ai/mastra/commit/b6a771ef23d203ddb348efca8065eff65def8191), [`9267e9b`](https://github.com/mastra-ai/mastra/commit/9267e9b3d9c2fcf16936050495a787054c2431ab), [`26d4016`](https://github.com/mastra-ai/mastra/commit/26d40160ff7f7d8bf95fee2039a52cbc83863533), [`9267e9b`](https://github.com/mastra-ai/mastra/commit/9267e9b3d9c2fcf16936050495a787054c2431ab), [`9267e9b`](https://github.com/mastra-ai/mastra/commit/9267e9b3d9c2fcf16936050495a787054c2431ab), [`57c5103`](https://github.com/mastra-ai/mastra/commit/57c51035a2a36e3df3c4f32f46bb789a66ed5946)]:
|
|
43
|
+
- @mastra/core@1.61.0-alpha.3
|
|
44
|
+
|
|
3
45
|
## 1.21.1-alpha.0
|
|
4
46
|
|
|
5
47
|
### Patch Changes
|
package/dist/docs/SKILL.md
CHANGED
|
@@ -46,7 +46,7 @@ const results = await store.query({
|
|
|
46
46
|
|
|
47
47
|
### Custom Operators
|
|
48
48
|
|
|
49
|
-
`$contains`Text contains substring{ description: { $contains: "sale" } }Supported by: Upstash, libSQL, PgVector, OracleDB`$regex`Regular expression match{ name: { $regex: "^test" } }Supported by: Qdrant, PgVector, Upstash, MongoDB, OracleDB`$size`Array length check{ tags: { $size: 3 } }Supported by: Astra, libSQL, PgVector, MongoDB, OracleDB`$geo`Geospatial query{ location: { $geo: { type: "radius", ... } } }Supported by: Qdrant`$datetime`Datetime range query{ created: { $datetime: { range: { gt: "2024-01-01" } } } }Supported by: Qdrant`$hasId`Vector ID existence check{ $hasId: \["id1", "id2"] }Supported by: Qdrant`$hasVector`Vector existence check{ $hasVector: true }Supported by: Qdrant
|
|
49
|
+
`$contains`Text contains substring{ description: { $contains: "sale" } }Supported by: Upstash, libSQL, PgVector, OracleDB`$regex`Regular expression match{ name: { $regex: "^test" } }Supported by: Qdrant, PgVector, Upstash, MongoDB, OracleDB`$size`Array length check{ tags: { $size: { $gt: 2 } } } — MongoDB requires an integer instead: { tags: { $size: 3 } }Supported by: Astra, libSQL, PgVector, MongoDB, OracleDB`$geo`Geospatial query{ location: { $geo: { type: "radius", ... } } }Supported by: Qdrant`$datetime`Datetime range query{ created: { $datetime: { range: { gt: "2024-01-01" } } } }Supported by: Qdrant`$hasId`Vector ID existence check{ $hasId: \["id1", "id2"] }Supported by: Qdrant`$hasVector`Vector existence check{ $hasVector: true }Supported by: Qdrant
|
|
50
50
|
|
|
51
51
|
## Common rules and restrictions
|
|
52
52
|
|
|
@@ -186,13 +186,21 @@ const results = await store.query({
|
|
|
186
186
|
|
|
187
187
|
### MongoDB
|
|
188
188
|
|
|
189
|
-
-
|
|
190
|
-
-
|
|
191
|
-
- Supports
|
|
192
|
-
-
|
|
193
|
-
-
|
|
194
|
-
|
|
195
|
-
|
|
189
|
+
- Requires MongoDB Atlas or a deployment with MongoDB Vector Search enabled. The store queries with the `$vectorSearch` aggregation stage.
|
|
190
|
+
- Uses MongoDB query syntax directly for metadata filters, including nested fields and arrays in metadata.
|
|
191
|
+
- Supports the comparison, array, logical, and element operators in the tables above, plus `$regex` and `$size`. `$size` takes an integer, as in `{ tags: { $size: 3 } }`.
|
|
192
|
+
- Use `filter` to match fields in the metadata object and `documentFilter` to match the original document text. You can combine them in a single query.
|
|
193
|
+
- Declare the metadata fields you filter on in `filterFields` when you create the index. Mastra passes filters that use only declared fields and the operators MongoDB Vector Search accepts (`$and`, `$or`, `$eq`, `$ne`, `$gt`, `$gte`, `$lt`, `$lte`, `$in`, `$nin`) directly to `$vectorSearch`:
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
await store.createIndex({
|
|
197
|
+
indexName: 'my_index',
|
|
198
|
+
dimension: 1536,
|
|
199
|
+
filterFields: ['category', 'price'],
|
|
200
|
+
})
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
- Filters that reference an undeclared field or use another operator take a fallback path: Mastra pre-filters the collection and passes the matching document IDs to `$vectorSearch`. This works only while the ID set fits within MongoDB's 16 MB BSON document limit. On large collections the query fails once that limit is exceeded, so declare your filter fields for selective queries over large data sets.
|
|
196
204
|
|
|
197
205
|
### Couchbase
|
|
198
206
|
|
|
@@ -77,9 +77,19 @@ For detailed information about available operators and syntax, see the [Metadata
|
|
|
77
77
|
|
|
78
78
|
Basic filtering examples:
|
|
79
79
|
|
|
80
|
+
**MongoDB**:
|
|
81
|
+
|
|
80
82
|
```ts
|
|
83
|
+
import { MongoDBVector } from '@mastra/mongodb'
|
|
84
|
+
|
|
85
|
+
const mongoVector = new MongoDBVector({
|
|
86
|
+
id: 'mongodb-vector',
|
|
87
|
+
uri: process.env.MONGODB_URI,
|
|
88
|
+
dbName: process.env.MONGODB_DB_NAME,
|
|
89
|
+
})
|
|
90
|
+
|
|
81
91
|
// Simple equality filter
|
|
82
|
-
const
|
|
92
|
+
const equalityResults = await mongoVector.query({
|
|
83
93
|
indexName: 'embeddings',
|
|
84
94
|
queryVector: embedding,
|
|
85
95
|
topK: 10,
|
|
@@ -89,7 +99,7 @@ const results = await pgVector.query({
|
|
|
89
99
|
})
|
|
90
100
|
|
|
91
101
|
// Numeric comparison
|
|
92
|
-
const
|
|
102
|
+
const priceResults = await mongoVector.query({
|
|
93
103
|
indexName: 'embeddings',
|
|
94
104
|
queryVector: embedding,
|
|
95
105
|
topK: 10,
|
|
@@ -99,7 +109,7 @@ const results = await pgVector.query({
|
|
|
99
109
|
})
|
|
100
110
|
|
|
101
111
|
// Multiple conditions
|
|
102
|
-
const
|
|
112
|
+
const compoundResults = await mongoVector.query({
|
|
103
113
|
indexName: 'embeddings',
|
|
104
114
|
queryVector: embedding,
|
|
105
115
|
topK: 10,
|
|
@@ -111,7 +121,7 @@ const results = await pgVector.query({
|
|
|
111
121
|
})
|
|
112
122
|
|
|
113
123
|
// Array operations
|
|
114
|
-
const
|
|
124
|
+
const tagResults = await mongoVector.query({
|
|
115
125
|
indexName: 'embeddings',
|
|
116
126
|
queryVector: embedding,
|
|
117
127
|
topK: 10,
|
|
@@ -121,7 +131,64 @@ const results = await pgVector.query({
|
|
|
121
131
|
})
|
|
122
132
|
|
|
123
133
|
// Logical operators
|
|
124
|
-
const
|
|
134
|
+
const categoryResults = await mongoVector.query({
|
|
135
|
+
indexName: 'embeddings',
|
|
136
|
+
queryVector: embedding,
|
|
137
|
+
topK: 10,
|
|
138
|
+
filter: {
|
|
139
|
+
$or: [{ category: 'electronics' }, { category: 'accessories' }],
|
|
140
|
+
$and: [{ price: { $gt: 50 } }, { price: { $lt: 200 } }],
|
|
141
|
+
},
|
|
142
|
+
})
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
**pgVector**:
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
// Simple equality filter
|
|
149
|
+
const equalityResults = await pgVector.query({
|
|
150
|
+
indexName: 'embeddings',
|
|
151
|
+
queryVector: embedding,
|
|
152
|
+
topK: 10,
|
|
153
|
+
filter: {
|
|
154
|
+
source: 'article1.txt',
|
|
155
|
+
},
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
// Numeric comparison
|
|
159
|
+
const priceResults = await pgVector.query({
|
|
160
|
+
indexName: 'embeddings',
|
|
161
|
+
queryVector: embedding,
|
|
162
|
+
topK: 10,
|
|
163
|
+
filter: {
|
|
164
|
+
price: { $gt: 100 },
|
|
165
|
+
},
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
// Multiple conditions
|
|
169
|
+
const compoundResults = await pgVector.query({
|
|
170
|
+
indexName: 'embeddings',
|
|
171
|
+
queryVector: embedding,
|
|
172
|
+
topK: 10,
|
|
173
|
+
filter: {
|
|
174
|
+
category: 'electronics',
|
|
175
|
+
price: { $lt: 1000 },
|
|
176
|
+
inStock: true,
|
|
177
|
+
},
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
// Array operations
|
|
181
|
+
const tagResults = await pgVector.query({
|
|
182
|
+
indexName: 'embeddings',
|
|
183
|
+
queryVector: embedding,
|
|
184
|
+
topK: 10,
|
|
185
|
+
filter: {
|
|
186
|
+
tags: { $in: ['sale', 'new'] },
|
|
187
|
+
},
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
// Logical operators
|
|
191
|
+
const categoryResults = await pgVector.query({
|
|
125
192
|
indexName: 'embeddings',
|
|
126
193
|
queryVector: embedding,
|
|
127
194
|
topK: 10,
|
|
@@ -141,6 +208,47 @@ Common use cases for metadata filtering:
|
|
|
141
208
|
- Combine multiple conditions for precise querying
|
|
142
209
|
- Filter by document attributes (e.g., language, author)
|
|
143
210
|
|
|
211
|
+
### Where the filter is applied
|
|
212
|
+
|
|
213
|
+
Vector stores differ in _when_ they apply a metadata filter, which affects how filtered queries scale.
|
|
214
|
+
|
|
215
|
+
MongoDB can evaluate the filter inside the vector index itself. This keeps the query on a single round trip to `$vectorSearch`, so it avoids the pre-filter pass that collects matching document IDs and the 16 MB BSON limit that pass is subject to. Declaring the fields you filter on in `filterFields` when you create the index is what enables it:
|
|
216
|
+
|
|
217
|
+
```ts
|
|
218
|
+
// Declare the metadata fields you want to filter on
|
|
219
|
+
await mongoVector.createIndex({
|
|
220
|
+
indexName: 'embeddings',
|
|
221
|
+
dimension: 1536,
|
|
222
|
+
filterFields: ['source', 'price', 'category', 'inStock', 'tags'],
|
|
223
|
+
})
|
|
224
|
+
|
|
225
|
+
// createIndex() returns before the index finishes building
|
|
226
|
+
await mongoVector.waitForIndexReady({ indexName: 'embeddings' })
|
|
227
|
+
|
|
228
|
+
// The filter is applied during the index search
|
|
229
|
+
const results = await mongoVector.query({
|
|
230
|
+
indexName: 'embeddings',
|
|
231
|
+
queryVector: embedding,
|
|
232
|
+
topK: 10,
|
|
233
|
+
filter: { source: 'article1.txt' },
|
|
234
|
+
})
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Mastra passes the filter to the index only when every field it references is declared in `filterFields` and every operator is one the index accepts: `$and`, `$or`, `$eq`, `$ne`, `$gt`, `$gte`, `$lt`, `$lte`, `$in`, and `$nin`. A filter that uses an undeclared field or any other operator takes a fallback path: Mastra matches the collection first and passes the matching document IDs into the vector search. That fallback holds only while the ID set fits within MongoDB's 16 MB BSON document limit. On large collections the query fails once that limit is exceeded, so declare your filter fields when you expect selective filters over large data sets.
|
|
238
|
+
|
|
239
|
+
pgVector applies the filter as an ordinary query condition:
|
|
240
|
+
|
|
241
|
+
```ts
|
|
242
|
+
const results = await pgVector.query({
|
|
243
|
+
indexName: 'embeddings',
|
|
244
|
+
queryVector: embedding,
|
|
245
|
+
topK: 10,
|
|
246
|
+
filter: { source: 'article1.txt' },
|
|
247
|
+
})
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
Postgres vector indexes (HNSW and IVFFlat) can't restrict that search to rows matching a condition. When a filter is present, pgVector instead compares the query vector against every matching row and returns the closest `topK`. Results are exact, but the work grows with the number of rows the filter matches. Indexing the metadata column speeds up row retrieval. The distance comparisons still happen per row.
|
|
251
|
+
|
|
144
252
|
### Vector Query Tool
|
|
145
253
|
|
|
146
254
|
Sometimes you want to give your agent the ability to query a vector database directly. The Vector Query Tool allows your agent to be in charge of retrieval decisions, combining semantic search with optional filtering and reranking based on the agent's understanding of the user's needs.
|
package/dist/index.cjs
CHANGED
|
@@ -6338,7 +6338,7 @@ var DatasetsPG = class DatasetsPG extends _mastra_core_storage.DatasetsStorage {
|
|
|
6338
6338
|
schemaName: getSchemaName$5(this.#schema)
|
|
6339
6339
|
});
|
|
6340
6340
|
let result;
|
|
6341
|
-
if (args.datasetVersion !== void 0) result = await this.#db.client.oneOrNone(`SELECT * FROM ${tableName} WHERE "id" = $1 AND "datasetVersion"
|
|
6341
|
+
if (args.datasetVersion !== void 0) result = await this.#db.client.oneOrNone(`SELECT * FROM ${tableName} WHERE "id" = $1 AND "datasetVersion" <= $2 AND ("validTo" IS NULL OR "validTo" > $2) AND "isDeleted" = false ORDER BY "datasetVersion" DESC LIMIT 1`, [args.id, args.datasetVersion]);
|
|
6342
6342
|
else result = await this.#db.client.oneOrNone(`SELECT * FROM ${tableName} WHERE "id" = $1 AND "validTo" IS NULL AND "isDeleted" = false`, [args.id]);
|
|
6343
6343
|
return result ? this.transformItemRow(result) : null;
|
|
6344
6344
|
} catch (error) {
|
|
@@ -6596,7 +6596,8 @@ var ExperimentsPG = class ExperimentsPG extends _mastra_core_storage.Experiments
|
|
|
6596
6596
|
"experimentSetId",
|
|
6597
6597
|
"comparisonId",
|
|
6598
6598
|
"variantId",
|
|
6599
|
-
"trialIndex"
|
|
6599
|
+
"trialIndex",
|
|
6600
|
+
"scorerIds"
|
|
6600
6601
|
]
|
|
6601
6602
|
});
|
|
6602
6603
|
await this.#db.alterTable({
|
|
@@ -6608,7 +6609,8 @@ var ExperimentsPG = class ExperimentsPG extends _mastra_core_storage.Experiments
|
|
|
6608
6609
|
"comment",
|
|
6609
6610
|
"toolMockReport",
|
|
6610
6611
|
"organizationId",
|
|
6611
|
-
"projectId"
|
|
6612
|
+
"projectId",
|
|
6613
|
+
"attempt"
|
|
6612
6614
|
]
|
|
6613
6615
|
});
|
|
6614
6616
|
await this.createDefaultIndexes();
|
|
@@ -6718,9 +6720,13 @@ var ExperimentsPG = class ExperimentsPG extends _mastra_core_storage.Experiments
|
|
|
6718
6720
|
columns: ["experimentId"]
|
|
6719
6721
|
},
|
|
6720
6722
|
{
|
|
6721
|
-
name: "
|
|
6723
|
+
name: "idx_experiment_results_exp_item_attempt",
|
|
6722
6724
|
table: _mastra_core_storage.TABLE_EXPERIMENT_RESULTS,
|
|
6723
|
-
columns: [
|
|
6725
|
+
columns: [
|
|
6726
|
+
"experimentId",
|
|
6727
|
+
"itemId",
|
|
6728
|
+
"attempt"
|
|
6729
|
+
],
|
|
6724
6730
|
unique: true
|
|
6725
6731
|
},
|
|
6726
6732
|
{
|
|
@@ -6737,6 +6743,11 @@ var ExperimentsPG = class ExperimentsPG extends _mastra_core_storage.Experiments
|
|
|
6737
6743
|
}
|
|
6738
6744
|
async createDefaultIndexes() {
|
|
6739
6745
|
if (this.#skipDefaultIndexes) return;
|
|
6746
|
+
try {
|
|
6747
|
+
await this.#db.dropIndex("idx_experiment_results_exp_item");
|
|
6748
|
+
} catch (error) {
|
|
6749
|
+
this.logger?.warn?.("Failed to drop legacy index idx_experiment_results_exp_item:", error);
|
|
6750
|
+
}
|
|
6740
6751
|
for (const indexDef of this.getDefaultIndexDefinitions()) try {
|
|
6741
6752
|
await this.#db.createIndex(indexDef);
|
|
6742
6753
|
} catch (error) {
|
|
@@ -6768,8 +6779,9 @@ var ExperimentsPG = class ExperimentsPG extends _mastra_core_storage.Experiments
|
|
|
6768
6779
|
agentVersion: row.agentVersion ?? null,
|
|
6769
6780
|
organizationId: row.organizationId ?? null,
|
|
6770
6781
|
projectId: row.projectId ?? null,
|
|
6771
|
-
targetType: row.targetType,
|
|
6772
|
-
targetId: row.targetId,
|
|
6782
|
+
targetType: row.targetType ?? null,
|
|
6783
|
+
targetId: row.targetId ?? null,
|
|
6784
|
+
scorerIds: row.scorerIds ? (0, _mastra_core_storage.safelyParseJSON)(row.scorerIds) : null,
|
|
6773
6785
|
status: row.status,
|
|
6774
6786
|
totalItems: row.totalItems,
|
|
6775
6787
|
succeededCount: row.succeededCount,
|
|
@@ -6796,6 +6808,7 @@ var ExperimentsPG = class ExperimentsPG extends _mastra_core_storage.Experiments
|
|
|
6796
6808
|
startedAt: (0, _mastra_core_storage.ensureDate)(row.startedAtZ || row.startedAt),
|
|
6797
6809
|
completedAt: (0, _mastra_core_storage.ensureDate)(row.completedAtZ || row.completedAt),
|
|
6798
6810
|
retryCount: row.retryCount,
|
|
6811
|
+
attempt: row.attempt != null ? row.attempt : 0,
|
|
6799
6812
|
traceId: row.traceId ?? null,
|
|
6800
6813
|
status: row.status ?? null,
|
|
6801
6814
|
tags: row.tags ? (0, _mastra_core_storage.safelyParseJSON)(row.tags) : null,
|
|
@@ -6827,8 +6840,9 @@ var ExperimentsPG = class ExperimentsPG extends _mastra_core_storage.Experiments
|
|
|
6827
6840
|
agentVersion: input.agentVersion ?? null,
|
|
6828
6841
|
organizationId: input.organizationId ?? null,
|
|
6829
6842
|
projectId: input.projectId ?? null,
|
|
6830
|
-
targetType: input.targetType,
|
|
6831
|
-
targetId: input.targetId,
|
|
6843
|
+
targetType: input.targetType ?? null,
|
|
6844
|
+
targetId: input.targetId ?? null,
|
|
6845
|
+
scorerIds: input.scorerIds ?? null,
|
|
6832
6846
|
status: "pending",
|
|
6833
6847
|
totalItems: input.totalItems,
|
|
6834
6848
|
succeededCount: 0,
|
|
@@ -6856,8 +6870,9 @@ var ExperimentsPG = class ExperimentsPG extends _mastra_core_storage.Experiments
|
|
|
6856
6870
|
agentVersion: input.agentVersion ?? null,
|
|
6857
6871
|
organizationId: input.organizationId ?? null,
|
|
6858
6872
|
projectId: input.projectId ?? null,
|
|
6859
|
-
targetType: input.targetType,
|
|
6860
|
-
targetId: input.targetId,
|
|
6873
|
+
targetType: input.targetType ?? null,
|
|
6874
|
+
targetId: input.targetId ?? null,
|
|
6875
|
+
scorerIds: input.scorerIds ?? null,
|
|
6861
6876
|
status: "pending",
|
|
6862
6877
|
totalItems: input.totalItems,
|
|
6863
6878
|
succeededCount: 0,
|
|
@@ -7101,6 +7116,7 @@ var ExperimentsPG = class ExperimentsPG extends _mastra_core_storage.Experiments
|
|
|
7101
7116
|
startedAt: input.startedAt.toISOString(),
|
|
7102
7117
|
completedAt: input.completedAt.toISOString(),
|
|
7103
7118
|
retryCount: input.retryCount,
|
|
7119
|
+
attempt: input.attempt ?? 0,
|
|
7104
7120
|
traceId: input.traceId ?? null,
|
|
7105
7121
|
status: input.status ?? null,
|
|
7106
7122
|
tags: input.tags ?? null,
|
|
@@ -7122,6 +7138,7 @@ var ExperimentsPG = class ExperimentsPG extends _mastra_core_storage.Experiments
|
|
|
7122
7138
|
startedAt: input.startedAt,
|
|
7123
7139
|
completedAt: input.completedAt,
|
|
7124
7140
|
retryCount: input.retryCount,
|
|
7141
|
+
attempt: input.attempt ?? 0,
|
|
7125
7142
|
traceId: input.traceId ?? null,
|
|
7126
7143
|
status: input.status ?? null,
|
|
7127
7144
|
tags: input.tags ?? null,
|
|
@@ -7136,6 +7153,81 @@ var ExperimentsPG = class ExperimentsPG extends _mastra_core_storage.Experiments
|
|
|
7136
7153
|
}, error);
|
|
7137
7154
|
}
|
|
7138
7155
|
}
|
|
7156
|
+
async upsertExperimentResult(input) {
|
|
7157
|
+
try {
|
|
7158
|
+
const tableName = getTableName$5({
|
|
7159
|
+
indexName: _mastra_core_storage.TABLE_EXPERIMENT_RESULTS,
|
|
7160
|
+
schemaName: getSchemaName$5(this.#schema)
|
|
7161
|
+
});
|
|
7162
|
+
const attempt = input.attempt ?? 0;
|
|
7163
|
+
const row = await this.#db.client.tx(async (t) => {
|
|
7164
|
+
const existing = await t.oneOrNone(`SELECT "id" FROM ${tableName} WHERE "experimentId" = $1 AND "itemId" = $2 AND COALESCE("attempt", 0) = $3 FOR UPDATE`, [
|
|
7165
|
+
input.experimentId,
|
|
7166
|
+
input.itemId,
|
|
7167
|
+
attempt
|
|
7168
|
+
]);
|
|
7169
|
+
if (!existing) {
|
|
7170
|
+
const id = crypto.randomUUID();
|
|
7171
|
+
return t.one(`INSERT INTO ${tableName} (
|
|
7172
|
+
"id", "experimentId", "itemId", "itemDatasetVersion", "organizationId", "projectId",
|
|
7173
|
+
"input", "output", "groundTruth", "error", "startedAt", "completedAt",
|
|
7174
|
+
"retryCount", "attempt", "traceId", "status", "tags", "toolMockReport", "createdAt"
|
|
7175
|
+
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19)
|
|
7176
|
+
RETURNING *`, [
|
|
7177
|
+
id,
|
|
7178
|
+
input.experimentId,
|
|
7179
|
+
input.itemId,
|
|
7180
|
+
input.itemDatasetVersion ?? null,
|
|
7181
|
+
input.organizationId ?? null,
|
|
7182
|
+
input.projectId ?? null,
|
|
7183
|
+
JSON.stringify(input.input),
|
|
7184
|
+
input.output != null ? JSON.stringify(input.output) : null,
|
|
7185
|
+
input.groundTruth != null ? JSON.stringify(input.groundTruth) : null,
|
|
7186
|
+
input.error != null ? JSON.stringify(input.error) : null,
|
|
7187
|
+
input.startedAt.toISOString(),
|
|
7188
|
+
input.completedAt.toISOString(),
|
|
7189
|
+
input.retryCount,
|
|
7190
|
+
attempt,
|
|
7191
|
+
input.traceId ?? null,
|
|
7192
|
+
input.status ?? null,
|
|
7193
|
+
input.tags != null ? JSON.stringify(input.tags) : null,
|
|
7194
|
+
input.toolMockReport != null ? JSON.stringify(input.toolMockReport) : null,
|
|
7195
|
+
(/* @__PURE__ */ new Date()).toISOString()
|
|
7196
|
+
]);
|
|
7197
|
+
}
|
|
7198
|
+
return t.one(`UPDATE ${tableName} SET
|
|
7199
|
+
"itemDatasetVersion" = $2, "organizationId" = $3, "projectId" = $4,
|
|
7200
|
+
"input" = $5, "output" = $6, "groundTruth" = $7, "error" = $8,
|
|
7201
|
+
"startedAt" = $9, "completedAt" = $10, "retryCount" = $11, "attempt" = $12,
|
|
7202
|
+
"traceId" = $13, "status" = $14, "tags" = $15, "toolMockReport" = $16
|
|
7203
|
+
WHERE "id" = $1 RETURNING *`, [
|
|
7204
|
+
existing.id,
|
|
7205
|
+
input.itemDatasetVersion ?? null,
|
|
7206
|
+
input.organizationId ?? null,
|
|
7207
|
+
input.projectId ?? null,
|
|
7208
|
+
JSON.stringify(input.input),
|
|
7209
|
+
input.output != null ? JSON.stringify(input.output) : null,
|
|
7210
|
+
input.groundTruth != null ? JSON.stringify(input.groundTruth) : null,
|
|
7211
|
+
input.error != null ? JSON.stringify(input.error) : null,
|
|
7212
|
+
input.startedAt.toISOString(),
|
|
7213
|
+
input.completedAt.toISOString(),
|
|
7214
|
+
input.retryCount,
|
|
7215
|
+
attempt,
|
|
7216
|
+
input.traceId ?? null,
|
|
7217
|
+
input.status ?? null,
|
|
7218
|
+
input.tags != null ? JSON.stringify(input.tags) : null,
|
|
7219
|
+
input.toolMockReport != null ? JSON.stringify(input.toolMockReport) : null
|
|
7220
|
+
]);
|
|
7221
|
+
});
|
|
7222
|
+
return this.transformExperimentResultRow(row);
|
|
7223
|
+
} catch (error) {
|
|
7224
|
+
throw new _mastra_core_error.MastraError({
|
|
7225
|
+
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "UPSERT_EXPERIMENT_RESULT", "FAILED"),
|
|
7226
|
+
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
7227
|
+
category: _mastra_core_error.ErrorCategory.THIRD_PARTY
|
|
7228
|
+
}, error);
|
|
7229
|
+
}
|
|
7230
|
+
}
|
|
7139
7231
|
async updateExperimentResult(input) {
|
|
7140
7232
|
try {
|
|
7141
7233
|
const tableName = getTableName$5({
|
|
@@ -18940,9 +19032,14 @@ var ScoresPG = class ScoresPG extends _mastra_core_storage.ScoresStorage {
|
|
|
18940
19032
|
}, error);
|
|
18941
19033
|
}
|
|
18942
19034
|
try {
|
|
18943
|
-
const
|
|
19035
|
+
const suppliedId = parsedScore.id;
|
|
19036
|
+
const id = suppliedId ?? crypto.randomUUID();
|
|
18944
19037
|
const now = /* @__PURE__ */ new Date();
|
|
18945
|
-
const { scorer, preprocessStepResult, analyzeStepResult, metadata, input, output, additionalContext, requestContext, entity, ...rest } = parsedScore;
|
|
19038
|
+
const { id: _suppliedId, scorer, preprocessStepResult, analyzeStepResult, metadata, input, output, additionalContext, requestContext, entity, ...rest } = parsedScore;
|
|
19039
|
+
if (suppliedId) await this.#db.client.none(`DELETE FROM ${getTableName$1({
|
|
19040
|
+
indexName: _mastra_core_storage.TABLE_SCORERS,
|
|
19041
|
+
schemaName: getSchemaName$1(this.#schema)
|
|
19042
|
+
})} WHERE id = $1`, [suppliedId]);
|
|
18946
19043
|
await this.#db.insert({
|
|
18947
19044
|
tableName: _mastra_core_storage.TABLE_SCORERS,
|
|
18948
19045
|
record: {
|