@mastra/oracledb 0.2.0 → 0.2.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 +26 -0
- package/dist/docs/SKILL.md +2 -2
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/docs-memory-observational-memory.md +13 -13
- package/dist/docs/references/docs-memory-semantic-recall.md +1 -1
- package/dist/docs/references/docs-memory-working-memory.md +3 -3
- package/dist/docs/references/{docs-storage-overview.md → docs-storage.md} +9 -7
- package/dist/docs/references/reference-rag-metadata-filters.md +17 -9
- package/dist/docs/references/reference-rag-retrieval.md +139 -23
- package/dist/index.cjs +5 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/workflows/index.d.ts.map +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# @mastra/oracledb
|
|
2
2
|
|
|
3
|
+
## 0.2.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 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))
|
|
8
|
+
|
|
9
|
+
- 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))
|
|
10
|
+
|
|
11
|
+
- 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))
|
|
12
|
+
|
|
13
|
+
- 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)]:
|
|
14
|
+
- @mastra/core@1.61.0
|
|
15
|
+
|
|
16
|
+
## 0.2.1-alpha.0
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- 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))
|
|
21
|
+
|
|
22
|
+
- 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))
|
|
23
|
+
|
|
24
|
+
- 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))
|
|
25
|
+
|
|
26
|
+
- Updated dependencies [[`88d14ca`](https://github.com/mastra-ai/mastra/commit/88d14cac008582a618fecc3d5c7fd3bdf4f6ddc3), [`84a5b69`](https://github.com/mastra-ai/mastra/commit/84a5b699f84d6bae0a34efe5a970d891090b9f41), [`84a5b69`](https://github.com/mastra-ai/mastra/commit/84a5b699f84d6bae0a34efe5a970d891090b9f41), [`84a5b69`](https://github.com/mastra-ai/mastra/commit/84a5b699f84d6bae0a34efe5a970d891090b9f41), [`038b7b4`](https://github.com/mastra-ai/mastra/commit/038b7b405cb4ac25ab3f3031334111b1f87ac112), [`4132d61`](https://github.com/mastra-ai/mastra/commit/4132d61f8367077120ee9e6420d3224dffd93c93)]:
|
|
27
|
+
- @mastra/core@1.60.1-alpha.0
|
|
28
|
+
|
|
3
29
|
## 0.2.0
|
|
4
30
|
|
|
5
31
|
### Minor Changes
|
package/dist/docs/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: mastra-oracledb
|
|
|
3
3
|
description: Documentation for @mastra/oracledb. Use when working with @mastra/oracledb APIs, configuration, or implementation.
|
|
4
4
|
metadata:
|
|
5
5
|
package: "@mastra/oracledb"
|
|
6
|
-
version: "0.2.
|
|
6
|
+
version: "0.2.1"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
## When to use
|
|
@@ -19,7 +19,7 @@ Read the individual reference documents for detailed explanations and code examp
|
|
|
19
19
|
- [Observational Memory](references/docs-memory-observational-memory.md) - Learn how Observational Memory keeps your agent's context window small while preserving long-term memory across conversations.
|
|
20
20
|
- [Semantic recall](references/docs-memory-semantic-recall.md) - Learn how to use semantic recall in Mastra to retrieve relevant messages from past conversations using vector search and embeddings.
|
|
21
21
|
- [Working memory](references/docs-memory-working-memory.md) - Learn how to configure working memory in Mastra to store persistent user data, preferences.
|
|
22
|
-
- [Storage
|
|
22
|
+
- [Storage](references/docs-storage.md) - Configure storage for Mastra to persist runtime state across agents, workflows, observability, evals, schedules, and memory.
|
|
23
23
|
|
|
24
24
|
### Integrations
|
|
25
25
|
|
|
@@ -418,7 +418,7 @@ With default settings, the context window doesn't grow unbounded. It oscillates
|
|
|
418
418
|
3. **Repeat**: History grows from \~6k back toward 30k and shrinks again. Each cycle appends to the observation log, which grows much more slowly than raw history.
|
|
419
419
|
4. **Observations reach 40k**: The Reflector creates a smaller log from the current observations and any earlier reflections.
|
|
420
420
|
|
|
421
|
-
In the normal buffered cycle, raw history oscillates between roughly 6k and 30k tokens. The observation log stays around 40k tokens, however long the conversation runs. These are activation thresholds rather than hard caps
|
|
421
|
+
In the normal buffered cycle, raw history oscillates between roughly 6k and 30k tokens. The observation log stays around 40k tokens, however long the conversation runs. These are activation thresholds rather than hard caps, so history can grow past the threshold whenever background buffering doesn't keep pace. Above `blockAfter` (default `1.2`, \~36k tokens) activation is allowed to overshoot the retention target instead of activating fewer chunks. It doesn't drain the buffer, and with the default settings it removes the same amount of history as below the threshold. Reflection falls back to a synchronous run above its own `blockAfter` (\~48k tokens).
|
|
422
422
|
|
|
423
423
|
With [`shareTokenBudget`](https://mastra.ai/reference/memory/observational-memory) enabled, the two budgets pool together. While the observation log is small, message history can expand into the unused observation space (up to \~70k tokens with the defaults) before observation triggers. It then shrinks as observations accumulate.
|
|
424
424
|
|
|
@@ -714,23 +714,23 @@ When message tokens reach the `messageTokens` threshold, buffered chunks activat
|
|
|
714
714
|
|
|
715
715
|
Buffered observations also include continuation hints, a suggested next response and the current task, so the main agent maintains conversational continuity after activation shrinks the context window.
|
|
716
716
|
|
|
717
|
-
If the agent produces messages faster than the Observer can process them,
|
|
717
|
+
If the agent produces messages faster than the Observer can process them, the `blockAfter` safety threshold lets activation overshoot the retention target instead of activating fewer chunks. It never activates more chunks than are needed to reach that target, and with the default settings it changes nothing. A synchronous observation runs when the `messageTokens` threshold is reached and buffered activation didn't happen. Buffered activation usually preserves a minimum remaining context (the smaller of \~1k tokens or the configured retention floor), but a single buffered chunk that covers the whole pending window still activates and can leave less.
|
|
718
718
|
|
|
719
719
|
Reflection works similarly, the Reflector runs in the background when observations reach a fraction of the reflection threshold.
|
|
720
720
|
|
|
721
721
|
### Settings
|
|
722
722
|
|
|
723
|
-
| Setting | Default | What it controls
|
|
724
|
-
| ------------------------------------- | ------- |
|
|
725
|
-
| `observation.bufferTokens` | `0.2` | How often to buffer. `0.2` means every 20% of `messageTokens`. With the default 30k threshold, that's roughly every 6k tokens. Can also be an absolute token count (e.g. `5000`).
|
|
726
|
-
| `observation.bufferActivation` | `0.8` | How aggressively to clear the message window on activation. `0.8` means remove enough messages to keep only 20% of `messageTokens` remaining. Lower values keep more message history.
|
|
727
|
-
| `observation.blockAfter` | `1.2` | Safety net if buffering can't keep up. Values from 1 up to (but not including) 100 multiply `messageTokens`: at `1.2`,
|
|
728
|
-
| `activateAfterIdle` | none | Forces buffered observations to activate after a period of inactivity, even before `observation.messageTokens` is reached. Accepts a numeric millisecond value such as `300_000`, duration strings like `"5m"` or `"1hr"`, or `"auto"` for a provider-aware prompt cache TTL.
|
|
729
|
-
| `activateOnProviderChange` | `false` | Forces buffered observations to activate when the next step uses a different `provider/model` than the one that produced the latest assistant step. Use this when switching providers or models would invalidate prompt cache reuse.
|
|
730
|
-
| `reflection.bufferActivation` | `0.5` | When to start background reflection. `0.5` means reflection begins when observations reach 50% of the `observationTokens` threshold.
|
|
731
|
-
| `reflection.activateAfterIdle` | none | Opts buffered reflections into idle activation. Reflections don't inherit top-level `activateAfterIdle`.
|
|
732
|
-
| `reflection.activateOnProviderChange` | `false` | Opts buffered reflections into provider-change activation. Reflections don't inherit top-level `activateOnProviderChange`.
|
|
733
|
-
| `reflection.blockAfter` | `1.2` | Safety threshold for reflection
|
|
723
|
+
| Setting | Default | What it controls |
|
|
724
|
+
| ------------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
725
|
+
| `observation.bufferTokens` | `0.2` | How often to buffer. `0.2` means every 20% of `messageTokens`. With the default 30k threshold, that's roughly every 6k tokens. Can also be an absolute token count (e.g. `5000`). |
|
|
726
|
+
| `observation.bufferActivation` | `0.8` | How aggressively to clear the message window on activation. `0.8` means remove enough messages to keep only 20% of `messageTokens` remaining. Lower values keep more message history. |
|
|
727
|
+
| `observation.blockAfter` | `1.2` | Safety net if buffering can't keep up. Values from 1 up to (but not including) 100 multiply `messageTokens`: at `1.2`, the threshold is 36k tokens (1.2 × 30k). Above it, activation may overshoot the retention target instead of activating fewer chunks. Values of 100 or more are absolute token counts (e.g. `50_000`) and must be greater than `messageTokens`. |
|
|
728
|
+
| `activateAfterIdle` | none | Forces buffered observations to activate after a period of inactivity, even before `observation.messageTokens` is reached. Accepts a numeric millisecond value such as `300_000`, duration strings like `"5m"` or `"1hr"`, or `"auto"` for a provider-aware prompt cache TTL. |
|
|
729
|
+
| `activateOnProviderChange` | `false` | Forces buffered observations to activate when the next step uses a different `provider/model` than the one that produced the latest assistant step. Use this when switching providers or models would invalidate prompt cache reuse. |
|
|
730
|
+
| `reflection.bufferActivation` | `0.5` | When to start background reflection. `0.5` means reflection begins when observations reach 50% of the `observationTokens` threshold. |
|
|
731
|
+
| `reflection.activateAfterIdle` | none | Opts buffered reflections into idle activation. Reflections don't inherit top-level `activateAfterIdle`. |
|
|
732
|
+
| `reflection.activateOnProviderChange` | `false` | Opts buffered reflections into provider-change activation. Reflections don't inherit top-level `activateOnProviderChange`. |
|
|
733
|
+
| `reflection.blockAfter` | `1.2` | Safety threshold for reflection. Same value format as observation (absolute values must be greater than `observationTokens`), but above it reflection runs synchronously when no buffered reflection is ready to activate. |
|
|
734
734
|
|
|
735
735
|
If you're relying on prompt caching, set `activateAfterIdle` to `"auto"` or to a specific cache TTL. That way, once a thread has been idle long enough for the cache to expire, the next request can activate buffered observations first and send a smaller compressed context window.
|
|
736
736
|
|
|
@@ -270,7 +270,7 @@ Supported embedding models:
|
|
|
270
270
|
|
|
271
271
|
- **OpenAI**: `text-embedding-3-small`, `text-embedding-3-large`, `text-embedding-ada-002`
|
|
272
272
|
- **Google**: `gemini-embedding-001`
|
|
273
|
-
- **OpenRouter**: Access embedding models from
|
|
273
|
+
- **OpenRouter**: Access embedding models from multiple providers
|
|
274
274
|
|
|
275
275
|
```ts
|
|
276
276
|
import { Agent } from '@mastra/core/agent'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
> Discover all available pages from the documentation index: https://mastra.ai/llms.txt
|
|
2
2
|
|
|
3
|
-
# Working
|
|
3
|
+
# Working memory
|
|
4
4
|
|
|
5
5
|
While [message history](https://mastra.ai/docs/memory/message-history) and [semantic recall](https://mastra.ai/docs/memory/semantic-recall) help agents remember conversations, working memory allows them to maintain persistent information about users across interactions.
|
|
6
6
|
|
|
@@ -213,7 +213,7 @@ const paragraphMemory = new Memory({
|
|
|
213
213
|
|
|
214
214
|
## Structured working memory
|
|
215
215
|
|
|
216
|
-
Working memory can also be defined using a structured schema instead of a Markdown template.
|
|
216
|
+
Working memory can also be defined using a structured schema instead of a Markdown template. A [Standard JSON Schema](https://standardschema.dev/json-schema) ([Zod](https://zod.dev/), [Valibot](https://valibot.dev/), [ArkType](https://arktype.io/), etc.). When using a schema, the agent will see and update working memory as a JSON object matching your schema.
|
|
217
217
|
|
|
218
218
|
**Requirement:** You must specify either `template` or `schema`, but not both.
|
|
219
219
|
|
|
@@ -400,7 +400,7 @@ const response = await agent.generate('What do you know about me?', {
|
|
|
400
400
|
|
|
401
401
|
## Opt in to state signals (experimental)
|
|
402
402
|
|
|
403
|
-
By default, working memory reaches the model as part of the system message. You can opt into delivering it as a [state signal](https://mastra.ai/docs/
|
|
403
|
+
By default, working memory reaches the model as part of the system message. You can opt into delivering it as a [state signal](https://mastra.ai/docs/harness/signals) instead by setting `useStateSignals: true`:
|
|
404
404
|
|
|
405
405
|
```typescript
|
|
406
406
|
const memory = new Memory({
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
> Discover all available pages from the documentation index: https://mastra.ai/llms.txt
|
|
2
2
|
|
|
3
|
-
# Storage
|
|
3
|
+
# Storage
|
|
4
4
|
|
|
5
5
|
Storage is the persistence layer for the Mastra runtime. It keeps memory, workflow state, observability data, eval results, schedules, and long-running agent state available after a process restarts.
|
|
6
6
|
|
|
@@ -10,7 +10,7 @@ Storage powers:
|
|
|
10
10
|
- [Workflows](https://mastra.ai/docs/workflows/overview): Durable snapshots for suspended and resumed workflow runs.
|
|
11
11
|
- [Observability](https://mastra.ai/docs/observability/overview): Traces, spans, metrics, logs, and feedback.
|
|
12
12
|
- [Evals](https://mastra.ai/docs/evals/overview): Scores, datasets, experiments, and evaluation results.
|
|
13
|
-
- [Long-running agents](https://mastra.ai/docs/
|
|
13
|
+
- [Long-running agents](https://mastra.ai/docs/harness/durable-agents): Background tasks, schedules, goals, and thread state.
|
|
14
14
|
|
|
15
15
|
## When to configure storage
|
|
16
16
|
|
|
@@ -188,25 +188,27 @@ You can also route `observability` to a dedicated analytics backend. See the [ob
|
|
|
188
188
|
|
|
189
189
|
## Supported providers
|
|
190
190
|
|
|
191
|
-
Each provider page includes installation instructions, configuration parameters, and usage examples
|
|
191
|
+
Each provider page includes installation instructions, configuration parameters, and usage examples. libSQL is the fastest path for local development because it doesn't require running a separate database server.
|
|
192
192
|
|
|
193
|
+
- [Aurora DSQL](https://mastra.ai/integrations/databases/aurora-dsql)
|
|
194
|
+
- [ClickHouse](https://mastra.ai/integrations/databases/clickhouse)
|
|
193
195
|
- [Cloudflare D1](https://mastra.ai/integrations/databases/cloudflare-d1)
|
|
194
|
-
- [Cloudflare KV
|
|
196
|
+
- [Cloudflare KV](https://mastra.ai/integrations/databases/cloudflare-kv)
|
|
195
197
|
- [Convex](https://mastra.ai/integrations/databases/convex)
|
|
198
|
+
- [DuckDB](https://mastra.ai/integrations/databases/duckdb)
|
|
196
199
|
- [DynamoDB](https://mastra.ai/integrations/databases/dynamodb)
|
|
197
200
|
- [Google Cloud Spanner](https://mastra.ai/integrations/databases/spanner)
|
|
198
201
|
- [LanceDB](https://mastra.ai/integrations/databases/lancedb)
|
|
199
202
|
- [libSQL](https://mastra.ai/integrations/databases/libsql)
|
|
200
|
-
- [
|
|
203
|
+
- [Mastra](https://mastra.ai/docs/mastra-platform/database)
|
|
201
204
|
- [MongoDB](https://mastra.ai/integrations/databases/mongodb)
|
|
205
|
+
- [MSSQL](https://mastra.ai/integrations/databases/mssql)
|
|
202
206
|
- [Neon Postgres](https://mastra.ai/integrations/databases/neon)
|
|
203
207
|
- [OracleDB](https://mastra.ai/integrations/databases/oracledb)
|
|
204
208
|
- [PostgreSQL](https://mastra.ai/integrations/databases/postgresql)
|
|
205
209
|
- [Redis](https://mastra.ai/integrations/databases/redis)
|
|
206
210
|
- [Upstash](https://mastra.ai/integrations/databases/upstash)
|
|
207
211
|
|
|
208
|
-
> **Tip:** libSQL is the fastest path for local development because it doesn't require running a separate database server.
|
|
209
|
-
|
|
210
212
|
## Next steps
|
|
211
213
|
|
|
212
214
|
- [Composite storage](https://mastra.ai/reference/storage/composite)
|
|
@@ -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
|
|
|
@@ -201,7 +209,7 @@ const results = await store.query({
|
|
|
201
209
|
### Amazon S3 Vectors
|
|
202
210
|
|
|
203
211
|
- Equality values must be primitives (string/number/boolean). `null`/`undefined`, arrays, objects, and Date aren't allowed for equality. Range operators accept numbers or Date (Dates are normalized to epoch ms).
|
|
204
|
-
- `$in`/`$nin` require **non-empty arrays of primitives
|
|
212
|
+
- `$in`/`$nin` require **non-empty arrays of primitives**. Date elements are allowed and normalized to epoch ms. **Array equality** isn't supported.
|
|
205
213
|
- Implicit AND is canonicalized (`{a:1,b:2}` → `{$and:[{a:1},{b:2}]`). Logical operators must contain field conditions and use non-empty arrays. They may appear only at the root or within other logical operators (not inside field values).
|
|
206
214
|
- Keys listed in `nonFilterableMetadataKeys` at index creation are stored but not filterable. This setting is immutable.
|
|
207
215
|
- $exists requires a boolean value.
|
|
@@ -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.
|
|
@@ -266,6 +374,23 @@ For detailed configuration options and advanced usage, see the [Vector Query Too
|
|
|
266
374
|
|
|
267
375
|
Vector store prompts define query patterns and filtering capabilities for each vector database implementation. When implementing filtering, these prompts are required in the agent's instructions to specify valid operators and syntax for each vector store implementation.
|
|
268
376
|
|
|
377
|
+
**MongoDB**:
|
|
378
|
+
|
|
379
|
+
```ts
|
|
380
|
+
import { MONGODB_PROMPT } from '@mastra/mongodb'
|
|
381
|
+
|
|
382
|
+
export const ragAgent = new Agent({
|
|
383
|
+
id: 'rag-agent',
|
|
384
|
+
name: 'RAG Agent',
|
|
385
|
+
model: 'openai/gpt-5.6-sol',
|
|
386
|
+
instructions: `
|
|
387
|
+
Process queries using the provided context. Structure responses to be concise and relevant.
|
|
388
|
+
${MONGODB_PROMPT}
|
|
389
|
+
`,
|
|
390
|
+
tools: { vectorQueryTool },
|
|
391
|
+
})
|
|
392
|
+
```
|
|
393
|
+
|
|
269
394
|
**pgVector**:
|
|
270
395
|
|
|
271
396
|
```ts
|
|
@@ -402,23 +527,6 @@ export const ragAgent = new Agent({
|
|
|
402
527
|
})
|
|
403
528
|
```
|
|
404
529
|
|
|
405
|
-
**MongoDB**:
|
|
406
|
-
|
|
407
|
-
```ts
|
|
408
|
-
import { MONGODB_PROMPT } from '@mastra/mongodb'
|
|
409
|
-
|
|
410
|
-
export const ragAgent = new Agent({
|
|
411
|
-
id: 'rag-agent',
|
|
412
|
-
name: 'RAG Agent',
|
|
413
|
-
model: 'openai/gpt-5.6-sol',
|
|
414
|
-
instructions: `
|
|
415
|
-
Process queries using the provided context. Structure responses to be concise and relevant.
|
|
416
|
-
${MONGODB_PROMPT}
|
|
417
|
-
`,
|
|
418
|
-
tools: { vectorQueryTool },
|
|
419
|
-
})
|
|
420
|
-
```
|
|
421
|
-
|
|
422
530
|
**OpenSearch**:
|
|
423
531
|
|
|
424
532
|
```ts
|
|
@@ -520,7 +628,13 @@ The weights control how different factors influence the final ranking:
|
|
|
520
628
|
|
|
521
629
|
> **Note:** For semantic scoring to work properly during re-ranking, each result must include the text content in its `metadata.text` field.
|
|
522
630
|
|
|
523
|
-
You can also use other relevance score providers like Cohere or ZeroEntropy:
|
|
631
|
+
You can also use other relevance score providers like Voyage AI, Cohere, or ZeroEntropy:
|
|
632
|
+
|
|
633
|
+
```ts
|
|
634
|
+
import { VoyageRelevanceScorer } from '@mastra/voyageai'
|
|
635
|
+
|
|
636
|
+
const relevanceProvider = new VoyageRelevanceScorer({ model: 'rerank-2.5' })
|
|
637
|
+
```
|
|
524
638
|
|
|
525
639
|
```ts
|
|
526
640
|
const relevanceProvider = new CohereRelevanceScorer('rerank-v3.5')
|
|
@@ -530,6 +644,8 @@ const relevanceProvider = new CohereRelevanceScorer('rerank-v3.5')
|
|
|
530
644
|
const relevanceProvider = new ZeroEntropyRelevanceScorer('zerank-1')
|
|
531
645
|
```
|
|
532
646
|
|
|
647
|
+
Voyage AI provides dedicated reranking models: `rerank-2.5` and `rerank-2.5-lite` both allow up to 32,000 tokens for the query and any single document combined, and up to 600,000 tokens across a request. `VoyageRelevanceScorer` reads `VOYAGE_API_KEY` from the environment, or accepts an `apiKey` in its config.
|
|
648
|
+
|
|
533
649
|
The re-ranked results combine vector similarity with semantic understanding to improve retrieval quality.
|
|
534
650
|
|
|
535
651
|
For more details about re-ranking, see the [rerank()](https://mastra.ai/reference/rag/rerankWithScorer) method.
|
package/dist/index.cjs
CHANGED
|
@@ -8960,7 +8960,11 @@ var WorkflowsOracle = class _WorkflowsOracle extends storage.WorkflowsStorage {
|
|
|
8960
8960
|
if (!snapshot?.context) {
|
|
8961
8961
|
throw new Error(`Snapshot not found for runId ${runId}`);
|
|
8962
8962
|
}
|
|
8963
|
-
const
|
|
8963
|
+
const { expectedStatus, ...state } = opts;
|
|
8964
|
+
if (!storage.matchesExpectedWorkflowStatus(snapshot.status, expectedStatus)) {
|
|
8965
|
+
return void 0;
|
|
8966
|
+
}
|
|
8967
|
+
const updatedSnapshot = { ...snapshot, ...state };
|
|
8964
8968
|
await client.none(
|
|
8965
8969
|
`UPDATE ${this.table()} SET snapshot = :snapshot, ${WORKFLOW_UPDATED_AT} = :updatedAt WHERE workflow_name = :workflowName AND run_id = :runId`,
|
|
8966
8970
|
{ workflowName, runId, snapshot: jsonBind(updatedSnapshot), updatedAt: /* @__PURE__ */ new Date() }
|