@mastra/mcp-docs-server 1.1.46-alpha.2 → 1.1.46-alpha.4
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/.docs/docs/agent-builder/browser.md +1 -1
- package/.docs/docs/agent-builder/channels.md +1 -1
- package/.docs/docs/agent-builder/integrations.md +73 -0
- package/.docs/docs/agent-builder/overview.md +1 -0
- package/.docs/docs/agents/adding-voice.md +1 -1
- package/.docs/docs/agents/agent-approval.md +2 -2
- package/.docs/docs/agents/background-tasks.md +1 -1
- package/.docs/docs/agents/channels.md +2 -2
- package/.docs/docs/agents/code-mode.md +20 -56
- package/.docs/docs/agents/overview.md +1 -0
- package/.docs/docs/agents/sdk-agents.md +165 -1
- package/.docs/docs/agents/supervisor-agents.md +40 -2
- package/.docs/docs/agents/using-tools.md +59 -1
- package/.docs/docs/browser/agent-browser.md +1 -1
- package/.docs/docs/browser/browser-viewer.md +22 -15
- package/.docs/docs/browser/overview.md +1 -1
- package/.docs/docs/browser/stagehand.md +1 -1
- package/.docs/docs/editor/overview.md +6 -6
- package/.docs/docs/editor/prompts.md +3 -3
- package/.docs/docs/editor/tools.md +2 -2
- package/.docs/docs/evals/evals-with-memory.md +8 -8
- package/.docs/docs/mastra-platform/observability.md +1 -1
- package/.docs/docs/mastra-platform/server.md +1 -1
- package/.docs/docs/mcp/mcp-apps.md +4 -4
- package/.docs/docs/memory/observational-memory.md +1 -1
- package/.docs/docs/memory/working-memory.md +2 -2
- package/.docs/docs/observability/integrations/bridges/datadog.md +1 -1
- package/.docs/docs/observability/integrations/bridges/otel.md +1 -1
- package/.docs/docs/observability/integrations/exporters/laminar.md +1 -1
- package/.docs/docs/observability/integrations/exporters/langfuse.md +26 -1
- package/.docs/docs/observability/integrations/exporters/mastra-platform.md +1 -1
- package/.docs/docs/observability/integrations/exporters/mastra-storage.md +4 -4
- package/.docs/docs/observability/integrations/exporters/otel.md +1 -1
- package/.docs/docs/observability/integrations/overview.md +1 -1
- package/.docs/docs/observability/logging.md +1 -1
- package/.docs/docs/observability/metrics/overview.md +3 -3
- package/.docs/docs/observability/metrics/querying.md +2 -2
- package/.docs/docs/observability/storage.md +2 -2
- package/.docs/docs/observability/tracing/overview.md +1 -1
- package/.docs/docs/server/auth/fga.md +15 -15
- package/.docs/docs/server/auth/okta.md +2 -2
- package/.docs/docs/server/auth/workos.md +1 -1
- package/.docs/docs/server/custom-api-routes.md +1 -1
- package/.docs/docs/server/pubsub.md +4 -4
- package/.docs/docs/studio/auth.md +1 -1
- package/.docs/docs/studio/observability.md +3 -1
- package/.docs/docs/workflows/scheduled-workflows.md +13 -13
- package/.docs/docs/workspace/filesystem.md +1 -1
- package/.docs/docs/workspace/lsp.md +1 -1
- package/.docs/docs/workspace/overview.md +35 -1
- package/.docs/docs/workspace/sandbox.md +4 -3
- package/.docs/guides/build-your-ui/ai-sdk-ui.md +2 -2
- package/.docs/guides/deployment/aws-bedrock-agentcore.md +3 -3
- package/.docs/guides/deployment/inngest.md +5 -5
- package/.docs/guides/deployment/temporal.md +3 -3
- package/.docs/guides/getting-started/nestjs.md +1 -1
- package/.docs/guides/migrations/mastra-cloud.md +3 -3
- package/.docs/guides/migrations/upgrade-to-v1/overview.md +1 -1
- package/.docs/guides/migrations/upgrade-to-v1/tracing.md +1 -1
- package/.docs/models/gateways/custom-gateways.md +57 -7
- package/.docs/reference/acp/acp-agent.md +2 -2
- package/.docs/reference/agents/agent.md +44 -0
- package/.docs/reference/agents/channels.md +1 -1
- package/.docs/reference/agents/durable-agent.md +2 -2
- package/.docs/reference/agents/generate.md +2 -0
- package/.docs/reference/agents/generateLegacy.md +2 -0
- package/.docs/reference/ai-sdk/handle-chat-stream.md +1 -1
- package/.docs/reference/ai-sdk/to-ai-sdk-stream.md +1 -1
- package/.docs/reference/auth/okta.md +1 -1
- package/.docs/reference/auth/workos.md +1 -1
- package/.docs/reference/browser/agent-browser.md +1 -1
- package/.docs/reference/browser/browser-viewer.md +11 -9
- package/.docs/reference/browser/stagehand-browser.md +1 -1
- package/.docs/reference/cli/mastra.md +3 -1
- package/.docs/reference/client-js/responses.md +2 -2
- package/.docs/reference/client-js/workflows.md +1 -1
- package/.docs/reference/configuration.md +1 -1
- package/.docs/reference/core/mastra-model-gateway.md +15 -1
- package/.docs/reference/core/removeWorkspace.md +26 -0
- package/.docs/reference/editor/browser-provider.md +1 -1
- package/.docs/reference/editor/storage-browser-ref.md +3 -3
- package/.docs/reference/editor/storage-workspace-ref.md +1 -1
- package/.docs/reference/evals/rubric.md +113 -0
- package/.docs/reference/evals/trajectory-accuracy.md +3 -3
- package/.docs/reference/harness/harness-class.md +81 -62
- package/.docs/reference/index.md +5 -0
- package/.docs/reference/memory/serialized-memory-config.md +1 -1
- package/.docs/reference/observability/metrics/automatic-metrics.md +3 -3
- package/.docs/reference/observability/tracing/bridges/datadog.md +1 -1
- package/.docs/reference/observability/tracing/exporters/cloud-exporter.md +3 -3
- package/.docs/reference/observability/tracing/exporters/default-exporter.md +1 -1
- package/.docs/reference/observability/tracing/exporters/mastra-platform-exporter.md +5 -5
- package/.docs/reference/observability/tracing/exporters/mastra-storage-exporter.md +1 -1
- package/.docs/reference/observability/tracing/exporters/otel.md +1 -1
- package/.docs/reference/observability/tracing/processors/sensitive-data-filter.md +2 -2
- package/.docs/reference/processors/cost-guard-processor.md +2 -2
- package/.docs/reference/processors/processor-interface.md +4 -4
- package/.docs/reference/processors/response-cache.md +2 -2
- package/.docs/reference/processors/skill-search-processor.md +3 -3
- package/.docs/reference/processors/tool-search-processor.md +108 -4
- package/.docs/reference/pubsub/base.md +1 -1
- package/.docs/reference/pubsub/caching-pubsub.md +2 -2
- package/.docs/reference/pubsub/event-emitter.md +3 -3
- package/.docs/reference/pubsub/google-cloud-pubsub.md +1 -1
- package/.docs/reference/pubsub/redis-streams.md +1 -1
- package/.docs/reference/pubsub/unix-socket-pubsub.md +1 -1
- package/.docs/reference/server/nestjs-adapter.md +2 -2
- package/.docs/reference/signals/task-signal-provider.md +62 -0
- package/.docs/reference/storage/clickhouse.md +49 -4
- package/.docs/reference/storage/composite.md +33 -1
- package/.docs/reference/storage/convex.md +2 -2
- package/.docs/reference/storage/dsql.md +7 -7
- package/.docs/reference/storage/duckdb.md +3 -3
- package/.docs/reference/storage/redis.md +3 -3
- package/.docs/reference/storage/spanner.md +7 -7
- package/.docs/reference/streaming/agents/stream.md +2 -0
- package/.docs/reference/streaming/agents/streamLegacy.md +2 -0
- package/.docs/reference/streaming/agents/streamUntilIdle.md +1 -1
- package/.docs/reference/tools/brightdata.md +3 -3
- package/.docs/reference/tools/create-code-mode.md +124 -0
- package/.docs/reference/tools/create-tool.md +1 -1
- package/.docs/reference/tools/mcp-client.md +5 -5
- package/.docs/reference/tools/mcp-server.md +45 -0
- package/.docs/reference/tools/perplexity.md +4 -4
- package/.docs/reference/tools/tavily.md +3 -3
- package/.docs/reference/voice/aws-nova-sonic.md +1 -1
- package/.docs/reference/voice/google-gemini-live.md +1 -1
- package/.docs/reference/voice/inworld-realtime.md +5 -5
- package/.docs/reference/voice/inworld.md +1 -1
- package/.docs/reference/voice/sarvam.md +1 -1
- package/.docs/reference/workspace/agentcore-runtime-sandbox.md +7 -7
- package/.docs/reference/workspace/azure-blob-filesystem.md +2 -2
- package/.docs/reference/workspace/files-sdk-filesystem.md +3 -3
- package/.docs/reference/workspace/google-drive-filesystem.md +7 -7
- package/.docs/reference/workspace/modal-sandbox.md +1 -1
- package/.docs/reference/workspace/railway-sandbox.md +230 -0
- package/.docs/reference/workspace/vercel-microvm-sandbox.md +1 -1
- package/.docs/reference/workspace/vercel.md +2 -2
- package/.docs/reference/workspace/workspace-class.md +39 -3
- package/CHANGELOG.md +17 -0
- package/dist/chunk-GLPCVXXO.js +2075 -0
- package/dist/chunk-GLPCVXXO.js.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/stdio.js +1 -2070
- package/dist/stdio.js.map +1 -1
- package/package.json +4 -4
|
@@ -27,13 +27,17 @@ const toolSearch = new ToolSearchProcessor({
|
|
|
27
27
|
|
|
28
28
|
**options.tools** (`Record<string, Tool>`): All tools that can be searched and loaded dynamically. These tools are not immediately available to the agent — they must be discovered via search and loaded on demand.
|
|
29
29
|
|
|
30
|
-
**options.search** (`{ topK?: number; minScore?: number }`): Configuration for the search behavior.
|
|
30
|
+
**options.search** (`{ topK?: number; minScore?: number; autoLoad?: boolean }`): Configuration for the search behavior.
|
|
31
31
|
|
|
32
32
|
**options.search.topK** (`number`): Maximum number of tools to return in search results.
|
|
33
33
|
|
|
34
34
|
**options.search.minScore** (`number`): Minimum relevance score (0-1) for including a tool in search results.
|
|
35
35
|
|
|
36
|
-
**options.
|
|
36
|
+
**options.search.autoLoad** (`boolean`): When true, tools returned by search\_tools are activated immediately as part of the search. The load\_tool meta-tool is not exposed, collapsing the two-step search then load flow into a single search step. Discovered tools become available on the next turn. Keep topK conservative since every match is activated.
|
|
37
|
+
|
|
38
|
+
**options.storage** (`'in-memory' | 'context'`): Where loaded-tool state lives. 'in-memory' (default) tracks loaded tools in an in-memory map per thread with TTL cleanup (see ttl); state is lost on restart and anonymous requests share a 'default' entry. 'context' derives loaded state from the conversation messages — a tool is loaded while a search\_tools/load\_tool result naming it remains in the messages; it is restart-safe, requires no memory, and de-loads automatically once that result is no longer present in the messages. The 'context' store is opt-in.
|
|
39
|
+
|
|
40
|
+
**options.ttl** (`number`): Time-to-live for in-memory thread state, in milliseconds. Only applies to the default storage: 'in-memory' store; after this duration of inactivity thread state is cleaned up. Set to 0 to disable cleanup. Ignored by the 'context' store.
|
|
37
41
|
|
|
38
42
|
**options.filter** (`(args: ToolSearchFilterArgs) => boolean | Promise<boolean>`): Optional request-aware hook for hiding tools from search results, blocking tool loading, or hiding already-loaded tools for the current request.
|
|
39
43
|
|
|
@@ -45,6 +49,48 @@ const toolSearch = new ToolSearchProcessor({
|
|
|
45
49
|
|
|
46
50
|
**processInputStep** (`(args: ProcessInputStepArgs) => Promise<ProcessInputStepResult>`): Processes each step to inject search/load meta-tools and any previously loaded tools into the agent's tool set.
|
|
47
51
|
|
|
52
|
+
## Methods
|
|
53
|
+
|
|
54
|
+
### State inspection (legacy `'in-memory'` store)
|
|
55
|
+
|
|
56
|
+
These methods operate on the default `'in-memory'` store only. They're no-ops for the `'context'` store, whose state lives in the conversation messages rather than an in-process map.
|
|
57
|
+
|
|
58
|
+
#### `clearState(threadId)`
|
|
59
|
+
|
|
60
|
+
Clears the loaded-tool state for a single thread.
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
processor.clearState('thread-123')
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
#### `clearAllState()`
|
|
67
|
+
|
|
68
|
+
Clears loaded-tool state for every thread.
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
processor.clearAllState()
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
#### `getStateStats()`
|
|
75
|
+
|
|
76
|
+
Returns the number of tracked threads and the oldest access time, for debugging in-memory growth.
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
const { threadCount, oldestAccessTime } = processor.getStateStats()
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Returns: `{ threadCount: number; oldestAccessTime: number | null }`
|
|
83
|
+
|
|
84
|
+
#### `cleanupNow()`
|
|
85
|
+
|
|
86
|
+
Immediately runs TTL cleanup instead of waiting for the scheduled sweep.
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
const cleaned = processor.cleanupNow()
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Returns: `number` — the count of threads cleaned up.
|
|
93
|
+
|
|
48
94
|
## Request-aware filtering
|
|
49
95
|
|
|
50
96
|
Use `filter` to apply request-specific policy to dynamic tools. The hook receives the resolved tool ID as `toolName`, the tool, request context, and phase. `toolName` is the ID returned by `search_tools`, which may differ from the key used in the `tools` object.
|
|
@@ -70,9 +116,9 @@ The `phase` value describes where the filter is being applied:
|
|
|
70
116
|
|
|
71
117
|
- `search`: Filters results returned by `search_tools`.
|
|
72
118
|
- `load`: Blocks `load_tool` from loading disallowed tools.
|
|
73
|
-
- `active`: Hides already-loaded tools from the current request if they
|
|
119
|
+
- `active`: Hides already-loaded tools from the current request if they're no longer allowed.
|
|
74
120
|
|
|
75
|
-
If the hook throws or rejects, `ToolSearchProcessor` treats the tool as disallowed for that request. The hook may run for every matching search candidate, so keep async policy checks cheap or cached. The
|
|
121
|
+
If the hook throws or rejects, `ToolSearchProcessor` treats the tool as disallowed for that request. The hook may run for every matching search candidate, so keep async policy checks cheap or cached. The `search_tools` meta-tool is always available; `load_tool` is available unless `search.autoLoad` is enabled. Tools passed directly through the agent or `processInputStep` remain available unless you filter them outside `ToolSearchProcessor`.
|
|
76
122
|
|
|
77
123
|
## Extended usage example
|
|
78
124
|
|
|
@@ -114,6 +160,64 @@ The agent workflow is:
|
|
|
114
160
|
4. The loaded tool becomes available on the next turn
|
|
115
161
|
5. Agent uses the loaded tool normally
|
|
116
162
|
|
|
163
|
+
## Single-step discovery with `autoLoad`
|
|
164
|
+
|
|
165
|
+
Set `search.autoLoad` to `true` to skip the separate load step. The tools returned by `search_tools` are activated immediately, and the `load_tool` meta-tool isn't exposed. This removes one model turn per discovery, which lowers token usage and latency, and works the same across providers.
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
const toolSearch = new ToolSearchProcessor({
|
|
169
|
+
tools: allTools,
|
|
170
|
+
search: {
|
|
171
|
+
topK: 3,
|
|
172
|
+
autoLoad: true,
|
|
173
|
+
},
|
|
174
|
+
})
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
With `autoLoad` the workflow becomes:
|
|
178
|
+
|
|
179
|
+
1. Agent receives a user message
|
|
180
|
+
2. Agent calls `search_tools` with keywords
|
|
181
|
+
3. The matching tools are activated automatically and become available on the next turn
|
|
182
|
+
4. Agent uses the tool normally
|
|
183
|
+
|
|
184
|
+
Every match is activated, so keep `topK` small (for example, `3`) to avoid adding tools the agent didn't need. Activated tools are appended after existing tools, which keeps the cached prompt prefix stable for providers that support prompt caching.
|
|
185
|
+
|
|
186
|
+
## Loaded-tool storage
|
|
187
|
+
|
|
188
|
+
The `storage` option controls where the set of loaded tools is tracked. The default is `'in-memory'`; the `'context'` store is opt-in.
|
|
189
|
+
|
|
190
|
+
### `'in-memory'` (default)
|
|
191
|
+
|
|
192
|
+
Loaded tools are tracked in an in-memory map per thread, with TTL-based cleanup controlled by the `ttl` option (default one hour). This is the original behavior:
|
|
193
|
+
|
|
194
|
+
- Requires no memory configuration.
|
|
195
|
+
- State is lost on process restart.
|
|
196
|
+
- Requests with no thread ID share a single `'default'` entry.
|
|
197
|
+
|
|
198
|
+
Use `clearState`, `clearAllState`, `getStateStats`, and `cleanupNow` to inspect or reset this store.
|
|
199
|
+
|
|
200
|
+
### `'context'`
|
|
201
|
+
|
|
202
|
+
Loaded state is derived from the conversation messages: a tool is loaded while a `search_tools` or `load_tool` result naming it remains in the messages. This mode:
|
|
203
|
+
|
|
204
|
+
- Requires no memory configuration.
|
|
205
|
+
- Is restart-safe — the durable record is the persisted message history.
|
|
206
|
+
- De-loads a tool automatically once that result is no longer present in the messages.
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
import { ToolSearchProcessor } from '@mastra/core/processors'
|
|
210
|
+
|
|
211
|
+
const toolSearch = new ToolSearchProcessor({
|
|
212
|
+
tools: allTools,
|
|
213
|
+
storage: 'context',
|
|
214
|
+
})
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Loading tools is cache-friendly in both modes: loads are append-only, so the cached prompt prefix stays stable for providers that support prompt caching.
|
|
218
|
+
|
|
219
|
+
Unloading a tool changes the tool definitions sent to the model, which shifts the cached prefix and causes the next turn to pay a cache write instead of a cache hit. In `'in-memory'` mode this happens when a thread's state is evicted by `ttl`. In `'context'` mode it happens when a tool's discovery result is no longer present in the messages (for example, when older messages are trimmed) — the tool de-loads and the model must search for it again before reuse. This is expected: removing an unused tool trades one cache write for a smaller prefix on later turns.
|
|
220
|
+
|
|
117
221
|
## Combining with other processors
|
|
118
222
|
|
|
119
223
|
```typescript
|
|
@@ -165,7 +165,7 @@ await pubsub.subscribeFromOffset('my-topic', 42, event => {
|
|
|
165
165
|
|
|
166
166
|
### `SubscribeBatchOptions`
|
|
167
167
|
|
|
168
|
-
Per-subscription batching policy. The callback signature
|
|
168
|
+
Per-subscription batching policy. The callback signature doesn't change; a batch of N events becomes N consecutive callback invocations in publish order.
|
|
169
169
|
|
|
170
170
|
**maxSize** (`number`): Maximum events held before forcing a flush.
|
|
171
171
|
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
`CachingPubSub` wraps any [`PubSub`](https://mastra.ai/reference/pubsub/base) implementation and adds event caching and replay. It records every published event per topic in a cache, so a subscriber that connects late or reconnects after a disconnect can replay the events it missed before continuing with live events.
|
|
4
4
|
|
|
5
|
-
Use it to build resumable streams on top of a transport that
|
|
5
|
+
Use it to build resumable streams on top of a transport that doesn't keep history, such as [`EventEmitterPubSub`](https://mastra.ai/reference/pubsub/event-emitter). Transports that already persist events, such as [`RedisStreamsPubSub`](https://mastra.ai/reference/pubsub/redis-streams), don't need this wrapper.
|
|
6
6
|
|
|
7
|
-
`CachingPubSub` is transparent to batching: `subscribe()` forwards `options.batch` to the inner pub/sub, and `supportsNativeBatching` mirrors the inner's value. Wrapping an inner that
|
|
7
|
+
`CachingPubSub` is transparent to batching: `subscribe()` forwards `options.batch` to the inner pub/sub, and `supportsNativeBatching` mirrors the inner's value. Wrapping an inner that doesn't support batching results in unbatched delivery even when `options.batch` is passed.
|
|
8
8
|
|
|
9
9
|
## Usage example
|
|
10
10
|
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
Use it for single-process applications. For delivery across processes on one host, see [`UnixSocketPubSub`](https://mastra.ai/reference/pubsub/unix-socket-pubsub). For distributed delivery, see [`RedisStreamsPubSub`](https://mastra.ai/reference/pubsub/redis-streams) or [`GoogleCloudPubSub`](https://mastra.ai/reference/pubsub/google-cloud-pubsub).
|
|
6
6
|
|
|
7
|
-
Because it
|
|
7
|
+
Because it's in-process, events aren't persisted and aren't shared with other processes. Wrap it in [`CachingPubSub`](https://mastra.ai/reference/pubsub/caching-pubsub) when you need replay for resumable streams.
|
|
8
8
|
|
|
9
9
|
## Usage example
|
|
10
10
|
|
|
11
|
-
`EventEmitterPubSub` is used automatically when you
|
|
11
|
+
`EventEmitterPubSub` is used automatically when you don't configure a `pubsub` option, so most applications never construct it directly. Create one explicitly only when you want to configure or share it.
|
|
12
12
|
|
|
13
13
|
```typescript
|
|
14
14
|
import { Mastra } from '@mastra/core'
|
|
@@ -104,4 +104,4 @@ await pubsub.subscribe(
|
|
|
104
104
|
)
|
|
105
105
|
```
|
|
106
106
|
|
|
107
|
-
The buffer is in-memory and per-process, so batched state
|
|
107
|
+
The buffer is in-memory and per-process, so batched state isn't persisted and doesn't survive a restart. A flush triggered by `maxWaitMs` is best-effort: if a step such as a throwing `coalesce` fails, the error is surfaced through the configured `logger` rather than thrown. `flush()` drains every batched subscriber buffer before resolving.
|
|
@@ -57,7 +57,7 @@ export const mastra = new Mastra({
|
|
|
57
57
|
|
|
58
58
|
### `init(topicName, group?)`
|
|
59
59
|
|
|
60
|
-
Creates the topic and a subscription if they
|
|
60
|
+
Creates the topic and a subscription if they don't already exist, and returns the subscription. `subscribe` calls this internally, so you rarely call it directly.
|
|
61
61
|
|
|
62
62
|
```typescript
|
|
63
63
|
await pubsub.init('workflow.events')
|
|
@@ -105,4 +105,4 @@ await pubsub.close()
|
|
|
105
105
|
|
|
106
106
|
## Redelivery and reclaim
|
|
107
107
|
|
|
108
|
-
When a subscriber calls `nack`, the event is republished with an incremented `deliveryAttempt` and the original is acknowledged. Once an event reaches `maxDeliveryAttempts`, it
|
|
108
|
+
When a subscriber calls `nack`, the event is republished with an incremented `deliveryAttempt` and the original is acknowledged. Once an event reaches `maxDeliveryAttempts`, it's dropped instead of redelivered. Separately, each subscription periodically reclaims events that an earlier consumer in the group read but never acknowledged, controlled by `reclaimIntervalMs` and `reclaimIdleMs`.
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
Use it when several local processes need to share a stream, such as coordinating thread streams across the Mastra Code terminal interface. For single-process delivery, use [`EventEmitterPubSub`](https://mastra.ai/reference/pubsub/event-emitter). For distributed delivery across hosts, use [`RedisStreamsPubSub`](https://mastra.ai/reference/pubsub/redis-streams) or [`GoogleCloudPubSub`](https://mastra.ai/reference/pubsub/google-cloud-pubsub).
|
|
6
6
|
|
|
7
|
-
`UnixSocketPubSub` is a push transport: events arrive without a read loop, so Mastra
|
|
7
|
+
`UnixSocketPubSub` is a push transport: events arrive without a read loop, so Mastra doesn't run a pull worker for it.
|
|
8
8
|
|
|
9
9
|
## Usage example
|
|
10
10
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
The `@mastra/nestjs` package provides a NestJS module for running Mastra with the Express-based NestJS platform.
|
|
4
4
|
|
|
5
|
-
It
|
|
5
|
+
It's intentionally Express-only for v1. If Nest is bootstrapped with a different HTTP adapter, `MastraModule` throws during startup instead of attempting a partial integration.
|
|
6
6
|
|
|
7
7
|
> **Info:** For general adapter concepts, see [Server Adapters](https://mastra.ai/docs/server/server-adapters).
|
|
8
8
|
|
|
@@ -51,7 +51,7 @@ import { mastra } from './mastra'
|
|
|
51
51
|
export class AppModule {}
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
-
> **Note:** `MastraModule` registers a catch-all controller (`@All('*')`). If it
|
|
54
|
+
> **Note:** `MastraModule` registers a catch-all controller (`@All('*')`). If it's imported before your app modules, it can intercept unrelated routes and return 404s. To avoid conflicts, import `MastraModule` last or mount it under a dedicated prefix (e.g., `/api/v1/mastra`).
|
|
55
55
|
|
|
56
56
|
```typescript
|
|
57
57
|
import { NestFactory } from '@nestjs/core'
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# TaskSignalProvider
|
|
2
|
+
|
|
3
|
+
Bundles the built-in task tools (`task_write`, `task_update`, `task_complete`, `task_check`) and the `TaskStateProcessor` behind a single agent registration. Use it to add a structured, durable task list to an agent without wiring the tools and processor separately.
|
|
4
|
+
|
|
5
|
+
Extends [`SignalProvider`](https://mastra.ai/reference/signals/signal-provider). The task list is stored in the thread-scoped `tasks` storage domain (the source of truth) and projected onto the agent state-signal lane by the processor, so it survives observational-memory truncation without invalidating the prompt cache.
|
|
6
|
+
|
|
7
|
+
## Usage example
|
|
8
|
+
|
|
9
|
+
Register the provider on an agent that has `Memory` and a Mastra `storage`:
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
import { Agent } from '@mastra/core/agent'
|
|
13
|
+
import { TaskSignalProvider } from '@mastra/core/signals'
|
|
14
|
+
|
|
15
|
+
const agent = new Agent({
|
|
16
|
+
name: 'coder',
|
|
17
|
+
instructions: '...',
|
|
18
|
+
model,
|
|
19
|
+
memory,
|
|
20
|
+
signals: [new TaskSignalProvider()],
|
|
21
|
+
})
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
The Agent automatically merges the four task tools into its toolset and registers the processor on its input-processor chain. No other wiring is required.
|
|
25
|
+
|
|
26
|
+
Task tracking requires a memory-backed thread (`threadId` + `resourceId`). Without memory the task tools no-op and return a result explaining that task tracking requires agent memory. The `tasks` storage domain is wired in-memory by default, so task tracking works without configuring a storage backend.
|
|
27
|
+
|
|
28
|
+
## Constructor parameters
|
|
29
|
+
|
|
30
|
+
`TaskSignalProvider` takes no constructor arguments.
|
|
31
|
+
|
|
32
|
+
## Properties
|
|
33
|
+
|
|
34
|
+
**id** (`'task-signals'`): Stable identifier for the provider instance.
|
|
35
|
+
|
|
36
|
+
## Methods
|
|
37
|
+
|
|
38
|
+
### Agent integration
|
|
39
|
+
|
|
40
|
+
These methods are called automatically by the Agent when the provider is passed to `signals`. You normally do not call them directly.
|
|
41
|
+
|
|
42
|
+
#### `getTools()`
|
|
43
|
+
|
|
44
|
+
Returns the four task tools keyed by their tool ids (`task_write`, `task_update`, `task_complete`, `task_check`). The Agent merges these into its toolset.
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
const tools = new TaskSignalProvider().getTools()
|
|
48
|
+
// { task_write, task_update, task_complete, task_check }
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Returns: `Record<string, Tool>`
|
|
52
|
+
|
|
53
|
+
#### `getInputProcessors()`
|
|
54
|
+
|
|
55
|
+
Returns the provider's `TaskStateProcessor` instance. The Agent registers it on the input-processor chain, which propagates the Mastra instance so the processor can resolve the `tasks` store.
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
const [processor] = new TaskSignalProvider().getInputProcessors()
|
|
59
|
+
// processor instanceof TaskStateProcessor
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Returns: `InputProcessorOrWorkflow[]`
|
|
@@ -8,7 +8,7 @@ ClickHouse is most commonly used as the dedicated observability backend in a [co
|
|
|
8
8
|
|
|
9
9
|
Production observability for traces, logs, metrics, scores, and feedback.
|
|
10
10
|
|
|
11
|
-
For local development, use a composite store that combines [LibSQL](https://mastra.ai/reference/storage/libsql) (for memory and workflows) and `@mastra/duckdb` (for observability). Neither alone covers a development setup: LibSQL
|
|
11
|
+
For local development, use a composite store that combines [LibSQL](https://mastra.ai/reference/storage/libsql) (for memory and workflows) and `@mastra/duckdb` (for observability). Neither alone covers a development setup: LibSQL doesn't implement the observability domain, and DuckDB doesn't implement the other domains. See the [observability overview](https://mastra.ai/docs/observability/overview) for an example.
|
|
12
12
|
|
|
13
13
|
## Installation
|
|
14
14
|
|
|
@@ -44,7 +44,7 @@ You will also need a running ClickHouse server. See [Hosting options](#hosting-o
|
|
|
44
44
|
|
|
45
45
|
`ObservabilityStorageClickhouseVNext` is the current observability domain implementation. It uses an insert-only schema backed by `ReplacingMergeTree` and is optimized for the volume produced by traces, logs, metrics, scores, and feedback.
|
|
46
46
|
|
|
47
|
-
Compose it with another storage adapter so observability writes
|
|
47
|
+
Compose it with another storage adapter so observability writes don't contend with your application data:
|
|
48
48
|
|
|
49
49
|
```typescript
|
|
50
50
|
import { Mastra } from '@mastra/core'
|
|
@@ -85,7 +85,7 @@ export const mastra = new Mastra({
|
|
|
85
85
|
|
|
86
86
|
### Observability with the legacy domain
|
|
87
87
|
|
|
88
|
-
`ObservabilityStorageClickhouse` is the original observability adapter and remains supported for projects that
|
|
88
|
+
`ObservabilityStorageClickhouse` is the original observability adapter and remains supported for projects that haven't migrated to the vNext schema. The configuration shape is the same as the vNext class.
|
|
89
89
|
|
|
90
90
|
```typescript
|
|
91
91
|
import { ObservabilityStorageClickhouse } from '@mastra/clickhouse'
|
|
@@ -182,10 +182,55 @@ The same `client` form is accepted by `ObservabilityStorageClickhouse` and `Obse
|
|
|
182
182
|
|
|
183
183
|
**ttl** (`object`): Per-table TTL configuration applied at table creation time. Accepts row-level and column-level TTLs in interval units from \`NANOSECOND\` through \`YEAR\`.
|
|
184
184
|
|
|
185
|
+
**replication** (`{ cluster?: string; zookeeperPath?: string; replicaName?: string }`): Opt-in replicated table configuration for multi-replica ClickHouse clusters. When set, Mastra creates replicated MergeTree tables. When \`cluster\` is set, Mastra also adds \`ON CLUSTER\` to Mastra-owned data definition language (DDL).
|
|
186
|
+
|
|
185
187
|
**disableInit** (`boolean`): When \`true\`, the store does not run table creation or migrations on first use. Call \`storage.init()\` explicitly from your deployment scripts. (Default: `false`)
|
|
186
188
|
|
|
187
189
|
`ClickhouseStore` also accepts every option from `ClickHouseClientConfigOptions` (such as `database`, `request_timeout`, `compression`, `keep_alive`, and `max_open_connections`).
|
|
188
190
|
|
|
191
|
+
### Replicated clusters
|
|
192
|
+
|
|
193
|
+
Use `replication` when Mastra writes to a multi-replica ClickHouse cluster through a load balancer.
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
const storage = new ClickhouseStoreVNext({
|
|
197
|
+
id: 'clickhouse-storage',
|
|
198
|
+
url: process.env.CLICKHOUSE_URL!,
|
|
199
|
+
username: process.env.CLICKHOUSE_USERNAME!,
|
|
200
|
+
password: process.env.CLICKHOUSE_PASSWORD!,
|
|
201
|
+
replication: {
|
|
202
|
+
cluster: 'company_cluster',
|
|
203
|
+
},
|
|
204
|
+
})
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
When `replication` is set, Mastra rewrites its `MergeTree` and `ReplacingMergeTree` table engines to `ReplicatedMergeTree` and `ReplicatedReplacingMergeTree`. The default engine arguments are:
|
|
208
|
+
|
|
209
|
+
- `zookeeperPath`: `'/clickhouse/tables/{shard}/{database}/{table}'`
|
|
210
|
+
- `replicaName`: `'{replica}'`
|
|
211
|
+
|
|
212
|
+
The defaults match the most common self-managed convention. If your cluster's existing tables use a different layout (for example `/clickhouse/tables/{shard}/{table}` without the `{database}` segment), set `zookeeperPath` explicitly to match. Mastra does not read your cluster's convention from Keeper, so a mismatched default writes Mastra's metadata to a separate branch from the rest of the cluster.
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
new ClickhouseStoreVNext({
|
|
216
|
+
url: process.env.CLICKHOUSE_URL!,
|
|
217
|
+
username: process.env.CLICKHOUSE_USERNAME!,
|
|
218
|
+
password: process.env.CLICKHOUSE_PASSWORD!,
|
|
219
|
+
replication: {
|
|
220
|
+
cluster: 'company_cluster',
|
|
221
|
+
zookeeperPath: '/clickhouse/tables/{shard}/{table}',
|
|
222
|
+
},
|
|
223
|
+
})
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Set `cluster` to add `ON CLUSTER` to Mastra-owned DDL such as table creation, materialized view creation, column migrations, TTL changes, and table drops.
|
|
227
|
+
|
|
228
|
+
Manual maintenance such as `optimizeTable()` and `materializeTtl()` runs on every replica when `cluster` is set. These operations can be expensive on a large cluster. Prefer running them outside peak hours, and let routine merges happen on the background merge queue rather than triggering them on every restart.
|
|
229
|
+
|
|
230
|
+
If existing Mastra tables use local `MergeTree` or `ReplacingMergeTree` engines, initialization fails while `replication` is enabled. Mastra refuses to silently convert local tables because copy-and-swap is unsafe across replicas. To migrate, recreate the affected tables as `Replicated*` before enabling replication. The typical sequence is: rename the local table, run `CREATE TABLE ... ENGINE = ReplicatedMergeTree(...) ON CLUSTER ...`, run `INSERT INTO ... SELECT * FROM <renamed_local>`, then drop the renamed local table.
|
|
231
|
+
|
|
232
|
+
Do not set `replication` on ClickHouse Cloud. Cloud rewrites `MergeTree` to `SharedMergeTree` server-side, and explicit `ReplicatedMergeTree` engines produce incorrect DDL. `replication` is only for self-managed multi-replica clusters.
|
|
233
|
+
|
|
189
234
|
### Observability domain options
|
|
190
235
|
|
|
191
236
|
`ObservabilityStorageClickhouse` and `ObservabilityStorageClickhouseVNext` accept the same connection options as `ClickhouseStore` (`url`, `username`, `password`, or a pre-configured `client`).
|
|
@@ -261,7 +306,7 @@ Two ways to provision the database:
|
|
|
261
306
|
|
|
262
307
|
The same approach applies to other hosts with ephemeral filesystems. For application data that should also live off-host, pair this setup with a managed PostgreSQL or LibSQL/Turso instance for the `default` storage.
|
|
263
308
|
|
|
264
|
-
> **Warning:**
|
|
309
|
+
> **Warning:** Don't point an embedded backend like DuckDB at a path inside an ephemeral container filesystem. Data written there is lost when the container restarts, and on some platforms the path is read-only.
|
|
265
310
|
|
|
266
311
|
## Initialization
|
|
267
312
|
|
|
@@ -240,6 +240,38 @@ const storage = new MastraCompositeStore({
|
|
|
240
240
|
})
|
|
241
241
|
```
|
|
242
242
|
|
|
243
|
-
> **Note:** `ObservabilityStorageClickhouseVNext` is the current observability domain implementation. The legacy `ObservabilityStorageClickhouse` class is also exported and remains supported for projects that
|
|
243
|
+
> **Note:** `ObservabilityStorageClickhouseVNext` is the current observability domain implementation. The legacy `ObservabilityStorageClickhouse` class is also exported and remains supported for projects that haven't migrated. See the [ClickHouse storage reference](https://mastra.ai/reference/storage/clickhouse) for details.
|
|
244
|
+
|
|
245
|
+
### Replicated ClickHouse for multi-replica clusters
|
|
246
|
+
|
|
247
|
+
For self-managed ClickHouse clusters with multiple replicas, set `replication` so Mastra emits `ReplicatedMergeTree` engines and applies `ON CLUSTER` to its DDL:
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
import { MastraCompositeStore } from '@mastra/core/storage'
|
|
251
|
+
import { MemoryPG, WorkflowsPG, ScoresPG } from '@mastra/pg'
|
|
252
|
+
import { ObservabilityStorageClickhouseVNext } from '@mastra/clickhouse'
|
|
253
|
+
|
|
254
|
+
const storage = new MastraCompositeStore({
|
|
255
|
+
id: 'composite',
|
|
256
|
+
domains: {
|
|
257
|
+
memory: new MemoryPG({ connectionString: process.env.DATABASE_URL }),
|
|
258
|
+
workflows: new WorkflowsPG({ connectionString: process.env.DATABASE_URL }),
|
|
259
|
+
scores: new ScoresPG({ connectionString: process.env.DATABASE_URL }),
|
|
260
|
+
observability: new ObservabilityStorageClickhouseVNext({
|
|
261
|
+
url: process.env.CLICKHOUSE_URL,
|
|
262
|
+
username: process.env.CLICKHOUSE_USERNAME,
|
|
263
|
+
password: process.env.CLICKHOUSE_PASSWORD,
|
|
264
|
+
replication: {
|
|
265
|
+
cluster: 'production_cluster',
|
|
266
|
+
// Optional (defaults shown):
|
|
267
|
+
// zookeeperPath: '/clickhouse/tables/{shard}/{database}/{table}',
|
|
268
|
+
// replicaName: '{replica}',
|
|
269
|
+
},
|
|
270
|
+
}),
|
|
271
|
+
},
|
|
272
|
+
})
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
Do not set `replication` on ClickHouse Cloud. Cloud rewrites `MergeTree` to `SharedMergeTree` server-side. See the [ClickHouse storage reference](https://mastra.ai/reference/storage/clickhouse) for the full config shape and operator notes.
|
|
244
276
|
|
|
245
277
|
> **Info:** This approach is also required when using storage providers that don't support observability (like Convex, DynamoDB, or Cloudflare). See the [MastraStorageExporter documentation](https://mastra.ai/docs/observability/integrations/exporters/mastra-storage) for the full list of supported providers.
|
|
@@ -176,13 +176,13 @@ For very large cache namespaces, clear incrementally or use narrower prefixes to
|
|
|
176
176
|
|
|
177
177
|
During batched cleanup, cache metadata can temporarily use an internal `deleted` state. The next cleanup pass removes those rows. Avoid writing new values with the same prefix until `clear()` finishes.
|
|
178
178
|
|
|
179
|
-
`clear()` only removes rows whose stored `keyPrefix` exactly matches the configured `keyPrefix`. It
|
|
179
|
+
`clear()` only removes rows whose stored `keyPrefix` exactly matches the configured `keyPrefix`. It doesn't clear nested prefixes by string prefix matching. Each `listPush()` refreshes the list TTL using the cache's configured `ttlMs`.
|
|
180
180
|
|
|
181
181
|
Use a non-empty `keyPrefix` unless you intentionally want `clear()` to remove every cache key in the deployment. Expired list rows are reclaimed incrementally during reads and writes; `clear()` removes all rows for the prefix.
|
|
182
182
|
|
|
183
183
|
`ConvexServerCache` works best for durable replay of moderate-frequency events. For high-frequency token streams, prefer batching events or using a lower-latency cache backend.
|
|
184
184
|
|
|
185
|
-
`ConvexServerCache`
|
|
185
|
+
`ConvexServerCache` doesn't replace a distributed pub/sub transport. If your app needs live cross-process event delivery, configure a production pub/sub backend separately.
|
|
186
186
|
|
|
187
187
|
## Additional notes
|
|
188
188
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
The Aurora DSQL storage implementation provides storage using Amazon Aurora DSQL with IAM authentication.
|
|
4
4
|
|
|
5
|
-
Aurora DSQL
|
|
5
|
+
Aurora DSQL doesn't support PostgreSQL extensions (`CREATE EXTENSION`), including `pgvector`. For vector storage, use a separate vector store such as `@mastra/s3vectors`.
|
|
6
6
|
|
|
7
7
|
## Installation
|
|
8
8
|
|
|
@@ -170,7 +170,7 @@ const memoryStore = await storage.getStore('memory')
|
|
|
170
170
|
const thread = await memoryStore?.getThreadById({ threadId: '...' })
|
|
171
171
|
```
|
|
172
172
|
|
|
173
|
-
> **Warning:** If `init()`
|
|
173
|
+
> **Warning:** If `init()` isn't called, tables won't be created and storage operations will fail silently or throw errors.
|
|
174
174
|
|
|
175
175
|
### Direct Database and Pool Access
|
|
176
176
|
|
|
@@ -193,7 +193,7 @@ This approach is intended for advanced scenarios where low-level access is requi
|
|
|
193
193
|
|
|
194
194
|
#### IAM-only authentication
|
|
195
195
|
|
|
196
|
-
Connections are authenticated with IAM.
|
|
196
|
+
Connections are authenticated with IAM. No database passwords are required. `@mastra/dsql` uses `@aws/aurora-dsql-node-postgres-connector` to generate short-lived auth tokens. You can provide a custom credentials provider via `customCredentialsProvider`.
|
|
197
197
|
|
|
198
198
|
#### Single database, schema-based isolation
|
|
199
199
|
|
|
@@ -201,7 +201,7 @@ Each cluster exposes a single database named `postgres`. Logical separation is d
|
|
|
201
201
|
|
|
202
202
|
#### No PostgreSQL extensions
|
|
203
203
|
|
|
204
|
-
`CREATE EXTENSION`
|
|
204
|
+
`CREATE EXTENSION` isn't supported. This includes `pgvector`, `PostGIS`, and others. For vector storage, use a separate store such as `@mastra/s3vectors` alongside `DSQLStore`.
|
|
205
205
|
|
|
206
206
|
#### JSON stored as text
|
|
207
207
|
|
|
@@ -209,7 +209,7 @@ JSON/JSONB are available as query types but not as column types. `@mastra/dsql`
|
|
|
209
209
|
|
|
210
210
|
#### Schema and DDL constraints
|
|
211
211
|
|
|
212
|
-
Some PostgreSQL features
|
|
212
|
+
Some PostgreSQL features aren't available:
|
|
213
213
|
|
|
214
214
|
- Foreign key constraints
|
|
215
215
|
- `TRUNCATE`
|
|
@@ -219,7 +219,7 @@ Indexes are created asynchronously using `CREATE INDEX ASYNC`. The store's `init
|
|
|
219
219
|
|
|
220
220
|
#### Transactions and optimistic concurrency
|
|
221
221
|
|
|
222
|
-
Aurora DSQL uses optimistic concurrency control (OCC) and may return retriable OCC errors under contention.
|
|
222
|
+
Aurora DSQL uses optimistic concurrency control (OCC) and may return retriable OCC errors under contention. Limits exist on transaction duration and size. Large bulk operations should be split into smaller batches at the application level.
|
|
223
223
|
|
|
224
224
|
#### Connection lifetime
|
|
225
225
|
|
|
@@ -332,7 +332,7 @@ await storage.createIndex({
|
|
|
332
332
|
})
|
|
333
333
|
```
|
|
334
334
|
|
|
335
|
-
Aurora DSQL
|
|
335
|
+
Aurora DSQL doesn't allow `ASC`/`DESC` in `CREATE INDEX ASYNC`. If you include them, they will be automatically stripped.
|
|
336
336
|
|
|
337
337
|
### Index Options
|
|
338
338
|
|
|
@@ -6,11 +6,11 @@ For vector search, see the [DuckDB vector store reference](https://mastra.ai/ref
|
|
|
6
6
|
|
|
7
7
|
## When to use DuckDB
|
|
8
8
|
|
|
9
|
-
Local development of observability features. DuckDB is embedded and file-based, so it
|
|
9
|
+
Local development of observability features. DuckDB is embedded and file-based, so it doesn't require a server and starts instantly. It supports the same observability signals as ClickHouse, which makes it useful for testing dashboards and trace exploration before deploying to a production backend.
|
|
10
10
|
|
|
11
11
|
DuckDB currently implements only the `observability` domain. Pair it with another storage adapter (such as [LibSQL](https://mastra.ai/reference/storage/libsql)) for `memory` and `workflows` in a [composite storage](https://mastra.ai/reference/storage/composite) setup.
|
|
12
12
|
|
|
13
|
-
> **Warning:** DuckDB is for development and not recommended for production. It runs in-process, persists to a single local file, and
|
|
13
|
+
> **Warning:** DuckDB is for development and not recommended for production. It runs in-process, persists to a single local file, and doesn't work on platforms with ephemeral filesystems (such as Railway, Fly.io, Render, Heroku, or serverless containers). For production observability, use [ClickHouse](https://mastra.ai/reference/storage/clickhouse).
|
|
14
14
|
|
|
15
15
|
## Installation
|
|
16
16
|
|
|
@@ -110,7 +110,7 @@ const duckdb = new DuckDBStore({ path: ':memory:' })
|
|
|
110
110
|
|
|
111
111
|
### Lower-level types
|
|
112
112
|
|
|
113
|
-
`@mastra/duckdb` also exports `DuckDBConnection` for sharing a single underlying database across multiple Mastra storage instances, and the corresponding `DuckDBStorageConfig` type. Most applications
|
|
113
|
+
`@mastra/duckdb` also exports `DuckDBConnection` for sharing a single underlying database across multiple Mastra storage instances, and the corresponding `DuckDBStorageConfig` type. Most applications won't need these directly.
|
|
114
114
|
|
|
115
115
|
## Supported domains
|
|
116
116
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Redis Storage
|
|
2
2
|
|
|
3
|
-
The Redis storage implementation provides a high-performance storage solution using direct Redis connections via [node-redis](https://github.com/redis/node-redis) (the official Redis client for Node.js). It supports standalone Redis, and through custom client configuration, Redis Sentinel and Cluster deployments.
|
|
3
|
+
The Redis storage implementation provides a high-performance storage solution using direct Redis connections via [`node-redis`](https://github.com/redis/node-redis) (the official Redis client for Node.js). It supports standalone Redis, and through custom client configuration, Redis Sentinel and Cluster deployments.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -41,7 +41,7 @@ await storage.init()
|
|
|
41
41
|
|
|
42
42
|
### Using Pre-configured Client
|
|
43
43
|
|
|
44
|
-
For advanced configurations like Sentinel or Cluster, you can pass a pre-configured
|
|
44
|
+
For advanced configurations like Sentinel or Cluster, you can pass a pre-configured Redis client:
|
|
45
45
|
|
|
46
46
|
```typescript
|
|
47
47
|
import { RedisStore } from '@mastra/redis'
|
|
@@ -142,7 +142,7 @@ const storage = new RedisStore({
|
|
|
142
142
|
|
|
143
143
|
### Accessing the Underlying Client
|
|
144
144
|
|
|
145
|
-
You can access the underlying
|
|
145
|
+
You can access the underlying Redis client for custom operations:
|
|
146
146
|
|
|
147
147
|
```typescript
|
|
148
148
|
const storage = new RedisStore({
|
|
@@ -138,7 +138,7 @@ Two tables also carry Spanner-specific `STORED` generated columns that the adapt
|
|
|
138
138
|
|
|
139
139
|
Both are added via `ALTER TABLE ... ADD COLUMN IF NOT EXISTS` during `init()` and skipped under `initMode: 'validate'` (where the schema is owned externally). When the column is absent, the adapter falls back to a `JSON_VALUE` filter at runtime.
|
|
140
140
|
|
|
141
|
-
The adapter
|
|
141
|
+
The adapter doesn't create or use named schemas; use a dedicated database for isolation.
|
|
142
142
|
|
|
143
143
|
### Initialization
|
|
144
144
|
|
|
@@ -160,7 +160,7 @@ const mastra = new Mastra({
|
|
|
160
160
|
})
|
|
161
161
|
```
|
|
162
162
|
|
|
163
|
-
If you use storage directly, call `init()` once before the first operation. Spanner
|
|
163
|
+
If you use storage directly, call `init()` once before the first operation. Spanner doesn't allow concurrent schema changes, so `SpannerStore.init()` runs each domain's setup sequentially.
|
|
164
164
|
|
|
165
165
|
```typescript
|
|
166
166
|
const storage = new SpannerStore({
|
|
@@ -175,18 +175,18 @@ const memory = await storage.getStore('memory')
|
|
|
175
175
|
const thread = await memory?.getThreadById({ threadId: '...' })
|
|
176
176
|
```
|
|
177
177
|
|
|
178
|
-
> **Warning:** If `init()`
|
|
178
|
+
> **Warning:** If `init()` isn't called and `disableInit` is true, the required tables won't exist and storage operations will fail.
|
|
179
179
|
|
|
180
180
|
### GoogleSQL specifics
|
|
181
181
|
|
|
182
182
|
A few behaviors differ from other relational adapters:
|
|
183
183
|
|
|
184
|
-
- Upserts use `INSERT OR UPDATE`. Spanner
|
|
185
|
-
-
|
|
184
|
+
- Upserts use `INSERT OR UPDATE`. Spanner doesn't provide a `RETURNING` clause for upserts, so callers needing the post-write state must read it back.
|
|
185
|
+
- No `TRUNCATE` exists; `dangerouslyClearAll()` issues `DELETE WHERE TRUE`.
|
|
186
186
|
- Identifiers are quoted with backticks.
|
|
187
187
|
- DDL is applied through `database.updateSchema(...)`, which is asynchronous (long-running operation).
|
|
188
|
-
- `NULLS FIRST/LAST`
|
|
189
|
-
- JSON containment
|
|
188
|
+
- `NULLS FIRST/LAST` isn't supported. Ordering with NULL handling is emulated through an `IS NULL` ordering key.
|
|
189
|
+
- JSON containment isn't supported natively. `listTraces` `metadata` and `scope` filters compile to per-key `JSON_VALUE(...) = @v` equality checks, and `tags` filters compile to `EXISTS` over `JSON_QUERY_ARRAY(...)`. This differs from Postgres' `@>` containment operator (which can match nested structure in a single index scan) — most one-shot lookups still work but deeply nested structural matches aren't expressible.
|
|
190
190
|
|
|
191
191
|
### Direct database access
|
|
192
192
|
|
|
@@ -168,6 +168,8 @@ const stream = await agent.stream('message for agent')
|
|
|
168
168
|
|
|
169
169
|
**options.clientTools** (`ToolsInput`): Tools that are executed on the 'client' side of the request. These tools do not have execute functions in the definition.
|
|
170
170
|
|
|
171
|
+
**options.hooks** (`ToolHooks`): Per-execution hooks that run before and after tool calls. Overrides matching agent-level hooks for this execution. \`beforeToolCall\` can return \`{ proceed: false, output }\` to skip the tool call.
|
|
172
|
+
|
|
171
173
|
**options.savePerStep** (`boolean`): Save messages incrementally after each stream step completes (default: false).
|
|
172
174
|
|
|
173
175
|
**options.requireToolApproval** (`boolean`): When true, all tool calls require explicit approval before execution. The stream will emit \`tool-call-approval\` chunks and pause until \`approveToolCall()\` or \`declineToolCall()\` is called.
|
|
@@ -82,6 +82,8 @@ await agent.streamLegacy('message for agent')
|
|
|
82
82
|
|
|
83
83
|
**options.clientTools** (`ToolsInput`): Tools that are executed on the 'client' side of the request. These tools do not have execute functions in the definition.
|
|
84
84
|
|
|
85
|
+
**options.hooks** (`ToolHooks`): Per-execution hooks that run before and after tool calls. Overrides matching agent-level hooks for this execution. \`beforeToolCall\` can return \`{ proceed: false, output }\` to skip the tool call.
|
|
86
|
+
|
|
85
87
|
**options.savePerStep** (`boolean`): Save messages incrementally after each stream step completes (default: false).
|
|
86
88
|
|
|
87
89
|
**options.providerOptions** (`Record<string, Record<string, JSONValue>>`): Additional provider-specific options that are passed through to the underlying LLM provider. The structure is \`{ providerName: { optionKey: value } }\`. For example: \`{ openai: { reasoningEffort: 'high' }, anthropic: { maxTokens: 1000 } }\`.
|