@mastra/mongodb 1.18.1-alpha.0 → 1.18.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 +86 -0
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/reference-rag-retrieval.md +113 -5
- package/dist/index.cjs +62 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +62 -8
- 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 +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,91 @@
|
|
|
1
1
|
# @mastra/mongodb
|
|
2
2
|
|
|
3
|
+
## 1.18.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
|
+
- Fixed concurrent resume() calls on the same suspended workflow run executing downstream steps more than once. A resume now atomically claims the run before executing anything, so only one caller continues a given suspension. Losing callers throw WORKFLOW_RESUME_ALREADY_CLAIMED without running any steps. Fixes #20443 ([#21725](https://github.com/mastra-ai/mastra/pull/21725))
|
|
10
|
+
|
|
11
|
+
- 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))
|
|
12
|
+
|
|
13
|
+
- Workflow state updates now support an optional expectedStatus guard, so a status change is only applied when the stored run is in an expected state. This is what makes concurrent workflow resumes safe. ([#21725](https://github.com/mastra-ai/mastra/pull/21725))
|
|
14
|
+
|
|
15
|
+
- 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))
|
|
16
|
+
|
|
17
|
+
- Resume conflicts now return 409 Conflict. When a suspended workflow run has already been resumed by another caller, the resume endpoints respond with 409 instead of a generic error. ([#21725](https://github.com/mastra-ai/mastra/pull/21725))
|
|
18
|
+
|
|
19
|
+
- 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))
|
|
20
|
+
|
|
21
|
+
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.
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
// Caller drives the loop, Mastra runs each item
|
|
25
|
+
const { experimentId } = await dataset.createExperiment({
|
|
26
|
+
id: workflowRunId,
|
|
27
|
+
targetType: 'agent',
|
|
28
|
+
targetId: 'support-agent',
|
|
29
|
+
scorers: ['accuracy'],
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
await dataset.runExperimentItem({ experimentId, itemId });
|
|
33
|
+
|
|
34
|
+
// Or: caller runs everything, Mastra ingests results
|
|
35
|
+
const ingest = await dataset.createExperiment({ id: workflowRunId });
|
|
36
|
+
await dataset.submitExperimentResult({
|
|
37
|
+
experimentId: ingest.experimentId,
|
|
38
|
+
itemId,
|
|
39
|
+
output,
|
|
40
|
+
scores: [{ scorerId: 'accuracy', score: 0.92 }],
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const experiment = await dataset.finalizeExperiment({ experimentId });
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
- Updated dependencies [[`88d14ca`](https://github.com/mastra-ai/mastra/commit/88d14cac008582a618fecc3d5c7fd3bdf4f6ddc3), [`480e491`](https://github.com/mastra-ai/mastra/commit/480e491588bd6a7a1c9ee4407590ad625dd33952), [`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), [`84a5b69`](https://github.com/mastra-ai/mastra/commit/84a5b699f84d6bae0a34efe5a970d891090b9f41), [`9267e9b`](https://github.com/mastra-ai/mastra/commit/9267e9b3d9c2fcf16936050495a787054c2431ab), [`3bb88dd`](https://github.com/mastra-ai/mastra/commit/3bb88ddf07fb98f3cd16d3bff94e51cd3b45d011), [`d23e75d`](https://github.com/mastra-ai/mastra/commit/d23e75d57cc7cf5b9bfdbee896bf5a6a2484fed7), [`c8faa4e`](https://github.com/mastra-ai/mastra/commit/c8faa4e1cfebaec56b65e754e90b9fe46d153359), [`d378d75`](https://github.com/mastra-ai/mastra/commit/d378d7511f71309ed61a8f6b93cd0361dc6cb70f), [`84a5b69`](https://github.com/mastra-ai/mastra/commit/84a5b699f84d6bae0a34efe5a970d891090b9f41), [`26d4016`](https://github.com/mastra-ai/mastra/commit/26d40160ff7f7d8bf95fee2039a52cbc83863533), [`7c60df5`](https://github.com/mastra-ai/mastra/commit/7c60df5c7872343fbac5c3e5b1175c8076a5abfd), [`9267e9b`](https://github.com/mastra-ai/mastra/commit/9267e9b3d9c2fcf16936050495a787054c2431ab), [`84a5b69`](https://github.com/mastra-ai/mastra/commit/84a5b699f84d6bae0a34efe5a970d891090b9f41), [`f2031a4`](https://github.com/mastra-ai/mastra/commit/f2031a47445e8f67a89ba1309036816f97ab7a65), [`9267e9b`](https://github.com/mastra-ai/mastra/commit/9267e9b3d9c2fcf16936050495a787054c2431ab), [`cad4208`](https://github.com/mastra-ai/mastra/commit/cad42082e6aa1776168a94914f523334be45d929), [`8e529d4`](https://github.com/mastra-ai/mastra/commit/8e529d4ac754efef04b225841349e0da9edf89a6), [`57c5103`](https://github.com/mastra-ai/mastra/commit/57c51035a2a36e3df3c4f32f46bb789a66ed5946), [`038b7b4`](https://github.com/mastra-ai/mastra/commit/038b7b405cb4ac25ab3f3031334111b1f87ac112), [`4132d61`](https://github.com/mastra-ai/mastra/commit/4132d61f8367077120ee9e6420d3224dffd93c93), [`d378d75`](https://github.com/mastra-ai/mastra/commit/d378d7511f71309ed61a8f6b93cd0361dc6cb70f)]:
|
|
47
|
+
- @mastra/core@1.61.0
|
|
48
|
+
|
|
49
|
+
## 1.18.1-alpha.1
|
|
50
|
+
|
|
51
|
+
### Patch Changes
|
|
52
|
+
|
|
53
|
+
- 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))
|
|
54
|
+
|
|
55
|
+
- 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))
|
|
56
|
+
|
|
57
|
+
- 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))
|
|
58
|
+
|
|
59
|
+
- 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))
|
|
60
|
+
|
|
61
|
+
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.
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
// Caller drives the loop, Mastra runs each item
|
|
65
|
+
const { experimentId } = await dataset.createExperiment({
|
|
66
|
+
id: workflowRunId,
|
|
67
|
+
targetType: 'agent',
|
|
68
|
+
targetId: 'support-agent',
|
|
69
|
+
scorers: ['accuracy'],
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
await dataset.runExperimentItem({ experimentId, itemId });
|
|
73
|
+
|
|
74
|
+
// Or: caller runs everything, Mastra ingests results
|
|
75
|
+
const ingest = await dataset.createExperiment({ id: workflowRunId });
|
|
76
|
+
await dataset.submitExperimentResult({
|
|
77
|
+
experimentId: ingest.experimentId,
|
|
78
|
+
itemId,
|
|
79
|
+
output,
|
|
80
|
+
scores: [{ scorerId: 'accuracy', score: 0.92 }],
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
const experiment = await dataset.finalizeExperiment({ experimentId });
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
- 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)]:
|
|
87
|
+
- @mastra/core@1.61.0-alpha.3
|
|
88
|
+
|
|
3
89
|
## 1.18.1-alpha.0
|
|
4
90
|
|
|
5
91
|
### Patch Changes
|
package/dist/docs/SKILL.md
CHANGED
|
@@ -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
|
@@ -10,7 +10,7 @@ let _mastra_core_agent = require("@mastra/core/agent");
|
|
|
10
10
|
let _mastra_core_evals = require("@mastra/core/evals");
|
|
11
11
|
let _mastra_core_storage_domains_skills = require("@mastra/core/storage/domains/skills");
|
|
12
12
|
//#region package.json
|
|
13
|
-
var version = "1.18.1
|
|
13
|
+
var version = "1.18.1";
|
|
14
14
|
//#endregion
|
|
15
15
|
//#region src/vector/filter.ts
|
|
16
16
|
/**
|
|
@@ -3678,8 +3678,9 @@ function transformExperimentRow(row) {
|
|
|
3678
3678
|
datasetVersion: row.datasetVersion != null ? Number(row.datasetVersion) : null,
|
|
3679
3679
|
organizationId: row.organizationId ?? null,
|
|
3680
3680
|
projectId: row.projectId ?? null,
|
|
3681
|
-
targetType: row.targetType,
|
|
3682
|
-
targetId: row.targetId,
|
|
3681
|
+
targetType: row.targetType ?? null,
|
|
3682
|
+
targetId: row.targetId ?? null,
|
|
3683
|
+
scorerIds: row.scorerIds ?? null,
|
|
3683
3684
|
status: row.status,
|
|
3684
3685
|
totalItems: Number(row.totalItems ?? 0),
|
|
3685
3686
|
succeededCount: Number(row.succeededCount ?? 0),
|
|
@@ -3707,6 +3708,7 @@ function transformExperimentResultRow(row) {
|
|
|
3707
3708
|
startedAt: toDate(row.startedAt),
|
|
3708
3709
|
completedAt: toDate(row.completedAt),
|
|
3709
3710
|
retryCount: Number(row.retryCount ?? 0),
|
|
3711
|
+
attempt: row.attempt != null ? Number(row.attempt) : 0,
|
|
3710
3712
|
traceId: row.traceId ?? null,
|
|
3711
3713
|
status: row.status ?? null,
|
|
3712
3714
|
tags: Array.isArray(row.tags) ? row.tags : parseJsonField(row.tags) ?? null,
|
|
@@ -3849,7 +3851,8 @@ var MongoDBExperimentsStorage = class MongoDBExperimentsStorage extends _mastra_
|
|
|
3849
3851
|
collection: _mastra_core_storage.TABLE_EXPERIMENT_RESULTS,
|
|
3850
3852
|
keys: {
|
|
3851
3853
|
experimentId: 1,
|
|
3852
|
-
itemId: 1
|
|
3854
|
+
itemId: 1,
|
|
3855
|
+
attempt: 1
|
|
3853
3856
|
},
|
|
3854
3857
|
options: { unique: true }
|
|
3855
3858
|
},
|
|
@@ -3876,6 +3879,9 @@ var MongoDBExperimentsStorage = class MongoDBExperimentsStorage extends _mastra_
|
|
|
3876
3879
|
}
|
|
3877
3880
|
async createDefaultIndexes() {
|
|
3878
3881
|
if (this.#skipDefaultIndexes) return;
|
|
3882
|
+
try {
|
|
3883
|
+
await (await this.getCollection(_mastra_core_storage.TABLE_EXPERIMENT_RESULTS)).dropIndex("experimentId_1_itemId_1");
|
|
3884
|
+
} catch {}
|
|
3879
3885
|
for (const indexDef of this.getDefaultIndexDefinitions()) try {
|
|
3880
3886
|
await (await this.getCollection(indexDef.collection)).createIndex(indexDef.keys, indexDef.options);
|
|
3881
3887
|
} catch (error) {
|
|
@@ -3912,8 +3918,9 @@ var MongoDBExperimentsStorage = class MongoDBExperimentsStorage extends _mastra_
|
|
|
3912
3918
|
datasetVersion: input.datasetVersion ?? null,
|
|
3913
3919
|
organizationId: input.organizationId ?? null,
|
|
3914
3920
|
projectId: input.projectId ?? null,
|
|
3915
|
-
targetType: input.targetType,
|
|
3916
|
-
targetId: input.targetId,
|
|
3921
|
+
targetType: input.targetType ?? null,
|
|
3922
|
+
targetId: input.targetId ?? null,
|
|
3923
|
+
scorerIds: input.scorerIds ?? null,
|
|
3917
3924
|
status: "pending",
|
|
3918
3925
|
totalItems: input.totalItems,
|
|
3919
3926
|
succeededCount: 0,
|
|
@@ -4084,6 +4091,7 @@ var MongoDBExperimentsStorage = class MongoDBExperimentsStorage extends _mastra_
|
|
|
4084
4091
|
startedAt: input.startedAt,
|
|
4085
4092
|
completedAt: input.completedAt,
|
|
4086
4093
|
retryCount: input.retryCount,
|
|
4094
|
+
attempt: input.attempt ?? 0,
|
|
4087
4095
|
traceId: input.traceId ?? null,
|
|
4088
4096
|
status: input.status ?? null,
|
|
4089
4097
|
tags: input.tags ?? null,
|
|
@@ -4106,6 +4114,7 @@ var MongoDBExperimentsStorage = class MongoDBExperimentsStorage extends _mastra_
|
|
|
4106
4114
|
startedAt: input.startedAt,
|
|
4107
4115
|
completedAt: input.completedAt,
|
|
4108
4116
|
retryCount: input.retryCount,
|
|
4117
|
+
attempt: input.attempt ?? 0,
|
|
4109
4118
|
traceId: input.traceId ?? null,
|
|
4110
4119
|
status: input.status ?? null,
|
|
4111
4120
|
tags: input.tags ?? null,
|
|
@@ -4121,6 +4130,48 @@ var MongoDBExperimentsStorage = class MongoDBExperimentsStorage extends _mastra_
|
|
|
4121
4130
|
}, error);
|
|
4122
4131
|
}
|
|
4123
4132
|
}
|
|
4133
|
+
async upsertExperimentResult(input) {
|
|
4134
|
+
const attempt = input.attempt ?? 0;
|
|
4135
|
+
try {
|
|
4136
|
+
return transformExperimentResultRow(await (await this.getCollection(_mastra_core_storage.TABLE_EXPERIMENT_RESULTS)).findOneAndUpdate({
|
|
4137
|
+
experimentId: input.experimentId,
|
|
4138
|
+
itemId: input.itemId,
|
|
4139
|
+
$or: [{ attempt }, ...attempt === 0 ? [{ attempt: null }, { attempt: { $exists: false } }] : []]
|
|
4140
|
+
}, {
|
|
4141
|
+
$set: {
|
|
4142
|
+
itemDatasetVersion: input.itemDatasetVersion ?? null,
|
|
4143
|
+
organizationId: input.organizationId ?? null,
|
|
4144
|
+
projectId: input.projectId ?? null,
|
|
4145
|
+
input: input.input,
|
|
4146
|
+
output: input.output ?? null,
|
|
4147
|
+
groundTruth: input.groundTruth ?? null,
|
|
4148
|
+
error: input.error ?? null,
|
|
4149
|
+
startedAt: input.startedAt,
|
|
4150
|
+
completedAt: input.completedAt,
|
|
4151
|
+
retryCount: input.retryCount,
|
|
4152
|
+
attempt,
|
|
4153
|
+
traceId: input.traceId ?? null,
|
|
4154
|
+
status: input.status ?? null,
|
|
4155
|
+
tags: input.tags ?? null,
|
|
4156
|
+
toolMockReport: input.toolMockReport ?? null
|
|
4157
|
+
},
|
|
4158
|
+
$setOnInsert: {
|
|
4159
|
+
id: (0, crypto$1.randomUUID)(),
|
|
4160
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
4161
|
+
}
|
|
4162
|
+
}, {
|
|
4163
|
+
upsert: true,
|
|
4164
|
+
returnDocument: "after"
|
|
4165
|
+
}));
|
|
4166
|
+
} catch (error) {
|
|
4167
|
+
throw new _mastra_core_error.MastraError({
|
|
4168
|
+
id: (0, _mastra_core_storage.createStorageErrorId)("MONGODB", "UPSERT_EXPERIMENT_RESULT", "FAILED"),
|
|
4169
|
+
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
4170
|
+
category: _mastra_core_error.ErrorCategory.THIRD_PARTY,
|
|
4171
|
+
details: { experimentId: input.experimentId }
|
|
4172
|
+
}, error);
|
|
4173
|
+
}
|
|
4174
|
+
}
|
|
4124
4175
|
async updateExperimentResult(input) {
|
|
4125
4176
|
const updateFields = {};
|
|
4126
4177
|
if (input.status !== void 0) updateFields.status = input.status;
|
|
@@ -10060,7 +10111,8 @@ var ScoresStorageMongoDB = class ScoresStorageMongoDB extends _mastra_core_stora
|
|
|
10060
10111
|
}
|
|
10061
10112
|
try {
|
|
10062
10113
|
const now = /* @__PURE__ */ new Date();
|
|
10063
|
-
const
|
|
10114
|
+
const suppliedId = validatedScore.id;
|
|
10115
|
+
const scoreId = suppliedId ?? (0, crypto$1.randomUUID)();
|
|
10064
10116
|
const scorer = typeof validatedScore.scorer === "string" ? (0, _mastra_core_storage.safelyParseJSON)(validatedScore.scorer) : validatedScore.scorer;
|
|
10065
10117
|
const preprocessStepResult = typeof validatedScore.preprocessStepResult === "string" ? (0, _mastra_core_storage.safelyParseJSON)(validatedScore.preprocessStepResult) : validatedScore.preprocessStepResult;
|
|
10066
10118
|
const analyzeStepResult = typeof validatedScore.analyzeStepResult === "string" ? (0, _mastra_core_storage.safelyParseJSON)(validatedScore.analyzeStepResult) : validatedScore.analyzeStepResult;
|
|
@@ -10083,7 +10135,9 @@ var ScoresStorageMongoDB = class ScoresStorageMongoDB extends _mastra_core_stora
|
|
|
10083
10135
|
createdAt,
|
|
10084
10136
|
updatedAt
|
|
10085
10137
|
};
|
|
10086
|
-
|
|
10138
|
+
const collection = await this.getCollection(_mastra_core_storage.TABLE_SCORERS);
|
|
10139
|
+
if (suppliedId) await collection.replaceOne({ id: scoreId }, dataToSave, { upsert: true });
|
|
10140
|
+
else await collection.insertOne(dataToSave);
|
|
10087
10141
|
return { score: dataToSave };
|
|
10088
10142
|
} catch (error) {
|
|
10089
10143
|
throw new _mastra_core_error.MastraError({
|