@mastra/libsql 1.27.1 → 1.28.0
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/README.md +1 -1
- package/dist/docs/SKILL.md +2 -2
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/docs-agents-human-in-the-loop.md +26 -1
- package/dist/docs/references/docs-memory-memory-processors.md +49 -3
- package/dist/docs/references/docs-memory-semantic-recall.md +22 -20
- package/dist/docs/references/integrations-databases-libsql.md +1 -1
- package/dist/docs/references/{reference-vectors-libsql.md → integrations-vectors-libsql.md} +16 -0
- package/dist/docs/references/reference-core-mastra-class.md +3 -1
- package/dist/docs/references/reference-memory-memory-class.md +77 -0
- package/dist/docs/references/reference-rag-retrieval.md +5 -1
- package/dist/index.cjs +29 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +29 -5
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/background-tasks/index.d.ts +1 -0
- package/dist/storage/domains/background-tasks/index.d.ts.map +1 -1
- package/package.json +7 -7
package/README.md
CHANGED
package/dist/docs/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: mastra-libsql
|
|
|
3
3
|
description: Documentation for @mastra/libsql. Use when working with @mastra/libsql APIs, configuration, or implementation.
|
|
4
4
|
metadata:
|
|
5
5
|
package: "@mastra/libsql"
|
|
6
|
-
version: "1.
|
|
6
|
+
version: "1.28.0"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
## When to use
|
|
@@ -35,6 +35,7 @@ Read the individual reference documents for detailed explanations and code examp
|
|
|
35
35
|
- [GitHub](references/integrations-channels-github.md) - Subscribe Mastra agents to GitHub pull requests with @mastra/github-signals, polling modes, notification signals, and subscription management tools.
|
|
36
36
|
- [DynamoDB](references/integrations-databases-dynamodb.md) - Persist Mastra data in Amazon DynamoDB with a single-table ElectroDB design, configurable indexes, TTL support, credentials, and table initialization.
|
|
37
37
|
- [libSQL](references/integrations-databases-libsql.md) - Persist Mastra messages, workflow snapshots, traces, and eval scores in local or remote libSQL with managed tables and initialization options.
|
|
38
|
+
- [libSQL](references/integrations-vectors-libsql.md) - Store embeddings in a local libSQL database or Turso and run similarity search with metadata filtering from Mastra.
|
|
38
39
|
|
|
39
40
|
### Reference
|
|
40
41
|
|
|
@@ -48,7 +49,6 @@ Read the individual reference documents for detailed explanations and code examp
|
|
|
48
49
|
- [Retrieval, semantic search, reranking](references/reference-rag-retrieval.md) - After storing embeddings, you need to retrieve relevant chunks to answer user queries.
|
|
49
50
|
- [Reference: Composite storage](references/reference-storage-composite.md) - MastraCompositeStore can compose storage domains from different providers. Use it when you need different databases for different purposes.
|
|
50
51
|
- [Reference: Storage retention (prune)](references/reference-storage-retention.md) - prune() deletes rows. It caps growth and is safe to run against large tables (batched, bounded, resumable, cancellable).
|
|
51
|
-
- [Reference: libSQL vector store](references/reference-vectors-libsql.md) - Configure LibSQLVector for similarity search and metadata filtering with local libSQL, SQLite-compatible vector extensions, or Turso databases.
|
|
52
52
|
|
|
53
53
|
|
|
54
54
|
Read [assets/SOURCE_MAP.json](assets/SOURCE_MAP.json) for source code references.
|
|
@@ -116,7 +116,7 @@ const stream = await agent.stream('Clean up old records', {
|
|
|
116
116
|
})
|
|
117
117
|
```
|
|
118
118
|
|
|
119
|
-
The function can be asynchronous. For decisions that depend on the tool name and arguments, use a [classifier](https://mastra.ai/
|
|
119
|
+
The function can be asynchronous. For decisions that depend on the tool name and arguments, use a [classifier](https://mastra.ai/docs/classifier) to estimate whether the call needs human review:
|
|
120
120
|
|
|
121
121
|
```typescript
|
|
122
122
|
import { Classifier } from '@mastra/core/classifier'
|
|
@@ -589,6 +589,31 @@ A [supervisor agent](https://mastra.ai/docs/subagents) coordinates multiple suba
|
|
|
589
589
|
|
|
590
590
|
Tool approvals also propagate through multiple levels of delegation. If a supervisor delegates to subagent A, which delegates to subagent B that has a tool with `requireApproval: true`, the approval request still surfaces at the top-level supervisor.
|
|
591
591
|
|
|
592
|
+
### Identify which subagent tool paused
|
|
593
|
+
|
|
594
|
+
The supervisor raises a subagent's pause on its own delegation call, so `toolCallId` on the `tool-call-approval` or `tool-call-suspended` chunk is the supervisor's call to the subagent. Always pass that `toolCallId` when you approve, decline, or resume.
|
|
595
|
+
|
|
596
|
+
To show which of the subagent's tool calls paused, read these fields from the same payload:
|
|
597
|
+
|
|
598
|
+
- `delegatedToolCallId`: The ID of the subagent's tool call that paused. Use it to tell apart two pauses from the same delegation, such as a question followed by an approval.
|
|
599
|
+
- `delegatedToolName`: The name of the subagent's tool that paused.
|
|
600
|
+
|
|
601
|
+
With several levels of delegation, both fields name the deepest tool call, the one that actually paused. Memory saves them with the pause, so they're still there when you reload the conversation, and `generate()` returns them on `suspendPayload`.
|
|
602
|
+
|
|
603
|
+
```typescript
|
|
604
|
+
const stream = await supervisorAgent.stream('Draft and publish the report')
|
|
605
|
+
|
|
606
|
+
for await (const chunk of stream.fullStream) {
|
|
607
|
+
if (chunk.type === 'tool-call-approval' || chunk.type === 'tool-call-suspended') {
|
|
608
|
+
// Label the pause with the subagent tool call that caused it
|
|
609
|
+
console.log('Paused:', chunk.payload.delegatedToolName, chunk.payload.delegatedToolCallId)
|
|
610
|
+
|
|
611
|
+
// Pass the supervisor's delegation call when you approve, decline, or resume
|
|
612
|
+
console.log('Resume with:', chunk.payload.toolCallId)
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
```
|
|
616
|
+
|
|
592
617
|
### Approve and decline in supervisor agents
|
|
593
618
|
|
|
594
619
|
The example below creates a subagent with a tool requiring approval. When the tool triggers an approval request, it surfaces in the supervisor's stream as a `tool-call-approval` chunk:
|
|
@@ -12,13 +12,13 @@ Memory processors are [processors](https://mastra.ai/docs/agents/processors) tha
|
|
|
12
12
|
|
|
13
13
|
## Built-in memory processors
|
|
14
14
|
|
|
15
|
-
Mastra automatically adds these processors when memory is enabled:
|
|
15
|
+
Mastra automatically adds these processors when memory is enabled. `MemoryInputFilter` is added only when a memory store is available and stored history will be loaded:
|
|
16
16
|
|
|
17
17
|
### `MemoryInputFilter`
|
|
18
18
|
|
|
19
|
-
Trims client-echoed history before memory loaders run. For an existing thread, it keeps only the current user turn or new tool results. For an empty thread, it keeps the full initial input and removes provider item metadata from assistant parts that could refer to items that don't exist in storage.
|
|
19
|
+
Trims client-echoed history before memory loaders run. For an existing thread, it keeps only the current user turn or new tool results. For an empty thread, it keeps the full initial input and removes provider item metadata from assistant parts that could refer to items that don't exist in storage. When `retainFullInput: true` is set, it skips both the trim and the metadata strip and processes the input exactly as supplied, while stored history still loads.
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
By default, this processor runs first so `MessageHistory`, `SemanticRecall`, and Observational Memory receive only the new input they need.
|
|
22
22
|
|
|
23
23
|
### `MessageHistory`
|
|
24
24
|
|
|
@@ -320,6 +320,52 @@ const agent = new Agent({
|
|
|
320
320
|
|
|
321
321
|
Both scenarios are safe - guardrails prevent inappropriate content from being persisted to memory
|
|
322
322
|
|
|
323
|
+
## Aborted runs and saved messages
|
|
324
|
+
|
|
325
|
+
Cancelling a run and blocking it with a processor `abort()` both stop generation, but they save different things:
|
|
326
|
+
|
|
327
|
+
| What stops the run | Memory processors | What's persisted |
|
|
328
|
+
| ----------------------------- | ----------------- | ------------------------------------------------------------ |
|
|
329
|
+
| `abortSignal` from the caller | Still run | The user message and the assistant text the user already saw |
|
|
330
|
+
| `abort()` inside a processor | Skipped | Nothing; the tripwire blocks the save |
|
|
331
|
+
|
|
332
|
+
A caller cancellation goes through output processors like any other run, so the built-in `MessageHistory` processor saves the thread. The partial answer is stored as an ordinary assistant message with no error part, which means the next turn starts from what the user actually read.
|
|
333
|
+
|
|
334
|
+
```typescript
|
|
335
|
+
import { Agent } from '@mastra/core/agent'
|
|
336
|
+
import { Memory } from '@mastra/memory'
|
|
337
|
+
|
|
338
|
+
const memory = new Memory({ options: { lastMessages: 20 } })
|
|
339
|
+
const agent = new Agent({
|
|
340
|
+
id: 'writer',
|
|
341
|
+
name: 'writer',
|
|
342
|
+
instructions: 'You write step-by-step migration guides.',
|
|
343
|
+
model: 'openai/gpt-6.1-sol',
|
|
344
|
+
memory,
|
|
345
|
+
})
|
|
346
|
+
|
|
347
|
+
const controller = new AbortController()
|
|
348
|
+
const stream = await agent.stream('Write the migration guide.', {
|
|
349
|
+
memory: { thread: 'thread-1', resource: 'user-1' },
|
|
350
|
+
abortSignal: controller.signal,
|
|
351
|
+
onAbort: ({ steps, text }) => {
|
|
352
|
+
console.log(`Aborted after ${steps.length} steps with ${text?.length ?? 0} characters streamed`)
|
|
353
|
+
},
|
|
354
|
+
})
|
|
355
|
+
|
|
356
|
+
let streamed = ''
|
|
357
|
+
for await (const chunk of stream.fullStream) {
|
|
358
|
+
if (chunk.type !== 'text-delta') continue
|
|
359
|
+
streamed += chunk.payload.text
|
|
360
|
+
if (streamed.length > 200) controller.abort()
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// The partial answer is already in the thread
|
|
364
|
+
const { messages } = await memory.recall({ threadId: 'thread-1', resourceId: 'user-1' })
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
`onAbort` receives the steps that completed before the cancellation and the assistant text streamed for the in-flight step. For the abort lifecycle itself, including durable runs aborted by `runId`, see the [`stream()` reference](https://mastra.ai/reference/streaming/agents/stream).
|
|
368
|
+
|
|
323
369
|
## Handling large attachments
|
|
324
370
|
|
|
325
371
|
Some storage providers enforce record size limits that base64-encoded file attachments can exceed:
|
|
@@ -141,24 +141,24 @@ const agent = new Agent({
|
|
|
141
141
|
|
|
142
142
|
Each vector store page below includes installation instructions, configuration parameters, and usage examples:
|
|
143
143
|
|
|
144
|
-
- [Astra](https://mastra.ai/
|
|
145
|
-
- [Chroma](https://mastra.ai/
|
|
146
|
-
- [Cloudflare Vectorize](https://mastra.ai/
|
|
147
|
-
- [Convex](https://mastra.ai/
|
|
148
|
-
- [Couchbase](https://mastra.ai/
|
|
149
|
-
- [DuckDB](https://mastra.ai/
|
|
150
|
-
- [Elasticsearch](https://mastra.ai/
|
|
151
|
-
- [LanceDB](https://mastra.ai/
|
|
152
|
-
- [libSQL](https://mastra.ai/
|
|
153
|
-
- [MongoDB](https://mastra.ai/
|
|
154
|
-
- [OpenSearch](https://mastra.ai/
|
|
155
|
-
- [OracleDB](https://mastra.ai/
|
|
156
|
-
- [Pinecone](https://mastra.ai/
|
|
157
|
-
- [PostgreSQL](https://mastra.ai/
|
|
158
|
-
- [Qdrant](https://mastra.ai/
|
|
159
|
-
- [S3 Vectors](https://mastra.ai/
|
|
160
|
-
- [Turbopuffer](https://mastra.ai/
|
|
161
|
-
- [Upstash](https://mastra.ai/
|
|
144
|
+
- [Astra](https://mastra.ai/integrations/vectors/astra)
|
|
145
|
+
- [Chroma](https://mastra.ai/integrations/vectors/chroma)
|
|
146
|
+
- [Cloudflare Vectorize](https://mastra.ai/integrations/vectors/vectorize)
|
|
147
|
+
- [Convex](https://mastra.ai/integrations/vectors/convex)
|
|
148
|
+
- [Couchbase](https://mastra.ai/integrations/vectors/couchbase)
|
|
149
|
+
- [DuckDB](https://mastra.ai/integrations/vectors/duckdb)
|
|
150
|
+
- [Elasticsearch](https://mastra.ai/integrations/vectors/elasticsearch)
|
|
151
|
+
- [LanceDB](https://mastra.ai/integrations/vectors/lance)
|
|
152
|
+
- [libSQL](https://mastra.ai/integrations/vectors/libsql)
|
|
153
|
+
- [MongoDB](https://mastra.ai/integrations/vectors/mongodb)
|
|
154
|
+
- [OpenSearch](https://mastra.ai/integrations/vectors/opensearch)
|
|
155
|
+
- [OracleDB](https://mastra.ai/integrations/vectors/oracledb)
|
|
156
|
+
- [Pinecone](https://mastra.ai/integrations/vectors/pinecone)
|
|
157
|
+
- [PostgreSQL](https://mastra.ai/integrations/vectors/pg)
|
|
158
|
+
- [Qdrant](https://mastra.ai/integrations/vectors/qdrant)
|
|
159
|
+
- [S3 Vectors](https://mastra.ai/integrations/vectors/s3vectors)
|
|
160
|
+
- [Turbopuffer](https://mastra.ai/integrations/vectors/turbopuffer)
|
|
161
|
+
- [Upstash](https://mastra.ai/integrations/vectors/upstash)
|
|
162
162
|
|
|
163
163
|
## Recall configuration
|
|
164
164
|
|
|
@@ -250,7 +250,7 @@ const options = {
|
|
|
250
250
|
|
|
251
251
|
Some vector stores generate the embeddings themselves. With one of those, semantic recall runs without an `embedder`: the database embeds each message on write and the search string on arrival. The embedding provider stays out of your application entirely.
|
|
252
252
|
|
|
253
|
-
MongoDB does this through [Automated Embedding](https://mastra.ai/
|
|
253
|
+
MongoDB does this through [Automated Embedding](https://mastra.ai/integrations/vectors/mongodb): name a Voyage AI model on the vector store and leave the `embedder` out.
|
|
254
254
|
|
|
255
255
|
```typescript
|
|
256
256
|
import { Memory } from '@mastra/memory'
|
|
@@ -435,6 +435,8 @@ When using PostgreSQL as your vector store, you can optimize semantic recall per
|
|
|
435
435
|
|
|
436
436
|
PostgreSQL supports both IVFFlat and HNSW indexes. By default, Mastra creates an IVFFlat index, but HNSW indexes typically provide better performance, especially with OpenAI embeddings which use inner product distance.
|
|
437
437
|
|
|
438
|
+
Semantic recall always filters by thread or resource. PgVector uses the vector index for these searches only with HNSW on pgvector 0.8.0 or newer. With IVFFlat, each search compares the query against every message in the thread or resource.
|
|
439
|
+
|
|
438
440
|
```typescript
|
|
439
441
|
import { Memory } from '@mastra/memory'
|
|
440
442
|
import { PostgresStore, PgVector } from '@mastra/pg'
|
|
@@ -467,7 +469,7 @@ const agent = new Agent({
|
|
|
467
469
|
})
|
|
468
470
|
```
|
|
469
471
|
|
|
470
|
-
For detailed information about index configuration options and performance tuning, see the [PgVector configuration guide](https://mastra.ai/
|
|
472
|
+
For detailed information about index configuration options and performance tuning, see the [PgVector configuration guide](https://mastra.ai/integrations/vectors/pg).
|
|
471
473
|
|
|
472
474
|
## Disable semantic recall
|
|
473
475
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
[libSQL](https://docs.turso.tech/libsql) is an open-source, SQLite-compatible database that supports both local and remote deployments. It can be used to store message history, workflow snapshots, traces, and eval scores.
|
|
8
8
|
|
|
9
|
-
For vectors like semantic recall or traditional RAG, use [libSQL Vector](https://mastra.ai/
|
|
9
|
+
For vectors like semantic recall or traditional RAG, use [libSQL Vector](https://mastra.ai/integrations/vectors/libsql) which covers embeddings and vector search.
|
|
10
10
|
|
|
11
11
|
## Installation
|
|
12
12
|
|
|
@@ -75,6 +75,8 @@ const results = await store.query({
|
|
|
75
75
|
|
|
76
76
|
## Constructor options
|
|
77
77
|
|
|
78
|
+
**id** (`string`): Unique identifier for this vector store instance
|
|
79
|
+
|
|
78
80
|
**url** (`string`): libSQL database URL. Use ':memory:' for in-memory database, 'file:dbname.db' for local file, or a libSQL-compatible connection string like 'libsql://your-database.turso.io'.
|
|
79
81
|
|
|
80
82
|
**authToken** (`string`): Authentication token for Turso cloud databases
|
|
@@ -83,6 +85,12 @@ const results = await store.query({
|
|
|
83
85
|
|
|
84
86
|
**syncInterval** (`number`): Interval in milliseconds for database sync (Turso specific)
|
|
85
87
|
|
|
88
|
+
**maxRetries** (`number`): Total attempts allowed for a write that hits a database lock (SQLITE_BUSY, SQLITE_LOCKED, or a "database is locked" error). The default of 5 means one attempt plus at most four retries. Use at least 1: with 0 the write is never attempted and the call throws (Default: `5`)
|
|
89
|
+
|
|
90
|
+
**initialBackoffMs** (`number`): Backoff before the first retry, in milliseconds. Each later retry waits twice as long (Default: `100`)
|
|
91
|
+
|
|
92
|
+
**vectorTopKOverFetchMultiplier** (`number`): Over-fetch multiplier for vector_top_k queries that have metadata filters. Higher values improve recall at the cost of scanning more rows. Must be a positive integer, or the constructor throws (Default: `10`)
|
|
93
|
+
|
|
86
94
|
## Methods
|
|
87
95
|
|
|
88
96
|
### `createIndex()`
|
|
@@ -191,6 +199,14 @@ Delete multiple vectors by IDs or by metadata filter. Either `ids` or `filter` m
|
|
|
191
199
|
|
|
192
200
|
**filter** (`Record<string, any>`): Metadata filter to identify vectors to delete (mutually exclusive with ids)
|
|
193
201
|
|
|
202
|
+
### `close()`
|
|
203
|
+
|
|
204
|
+
Closes the underlying libSQL client and releases the file handles this vector store holds. Calling it more than once is a no-op.
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
await store.close()
|
|
208
|
+
```
|
|
209
|
+
|
|
194
210
|
## Response types
|
|
195
211
|
|
|
196
212
|
Query results are returned in this format:
|
|
@@ -77,7 +77,7 @@ Visit the [Configuration reference](https://mastra.ai/reference/configuration) f
|
|
|
77
77
|
|
|
78
78
|
**environment** (`string`): Deployment environment name (e.g. production, staging, development). When set, automatically attached to all observability signals so they can be filtered by environment without passing tracingOptions.metadata.environment on each call. When unset, resolves to development for mastra dev runs, then falls back to process.env.NODE_ENV; left undefined if none are set. Per-call tracingOptions.metadata.environment always takes precedence.
|
|
79
79
|
|
|
80
|
-
**deployer** (`
|
|
80
|
+
**deployer** (`IDeployer`): A deployer for managing deployments, such as VercelDeployer from @mastra/deployer-vercel.
|
|
81
81
|
|
|
82
82
|
**server** (`ServerConfig`): Server configuration including port, host, timeout, API routes, middleware, CORS settings, and build options for Swagger UI, API request logging, and OpenAPI docs.
|
|
83
83
|
|
|
@@ -123,6 +123,8 @@ Visit the [Configuration reference](https://mastra.ai/reference/configuration) f
|
|
|
123
123
|
|
|
124
124
|
**backgroundTasks.perAgentConcurrency** (`number`): Max concurrent tasks per agent.
|
|
125
125
|
|
|
126
|
+
**backgroundTasks.perOwnerConcurrency** (`Record<string, number>`): Per-owner overrides of perAgentConcurrency, keyed by agentId. Overridden owners still count toward globalConcurrency.
|
|
127
|
+
|
|
126
128
|
**backgroundTasks.backpressure** (`'queue' | 'reject' | 'fallback-sync'`): Behavior when concurrency limit is reached.
|
|
127
129
|
|
|
128
130
|
**backgroundTasks.defaultTimeoutMs** (`number`): Default task timeout in milliseconds.
|
|
@@ -61,6 +61,83 @@ export const agent = new Agent({
|
|
|
61
61
|
|
|
62
62
|
**memory** (`Memory`): A new Memory instance with the specified configuration.
|
|
63
63
|
|
|
64
|
+
## `saveMessages()`
|
|
65
|
+
|
|
66
|
+
`agent.generate()` and `agent.stream()` persist messages for you. Call `memory.saveMessages()` when you need to write messages yourself, for example to seed a thread, to import a transcript, or to store messages that originated outside Mastra. Each message needs a `threadId` and a `resourceId`, so create the thread with [`createThread()`](https://mastra.ai/reference/memory/createThread) before saving into it.
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
await memory.saveMessages({
|
|
70
|
+
messages: [
|
|
71
|
+
{
|
|
72
|
+
id: 'msg-1',
|
|
73
|
+
threadId: 'thread-123',
|
|
74
|
+
resourceId: 'user-456',
|
|
75
|
+
role: 'user',
|
|
76
|
+
createdAt: new Date(),
|
|
77
|
+
content: {
|
|
78
|
+
format: 2,
|
|
79
|
+
parts: [{ type: 'text', text: 'Where is my order?' }],
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
})
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Parameters
|
|
87
|
+
|
|
88
|
+
**messages** (`MastraDBMessage[]`): The messages to save. Every message must include a threadId and a resourceId.
|
|
89
|
+
|
|
90
|
+
**memoryConfig** (`MemoryConfig`): Per-call memory options. Merged over the options passed to the constructor.
|
|
91
|
+
|
|
92
|
+
**observabilityContext** (`Partial<ObservabilityContext>`): Tracing context attached to the save operation.
|
|
93
|
+
|
|
94
|
+
Returns `Promise<{ messages: MastraDBMessage[]; usage?: { tokens: number } }>`. `usage` is present when the embedder reports token usage while indexing messages for semantic recall.
|
|
95
|
+
|
|
96
|
+
### `MastraDBMessage`
|
|
97
|
+
|
|
98
|
+
Storage uses a single message shape, `MastraDBMessage`. The methods that hand messages back or take them in use this shape, including `saveMessages()` and [`recall()`](https://mastra.ai/reference/memory/recall).
|
|
99
|
+
|
|
100
|
+
**id** (`string`): Message identifier.
|
|
101
|
+
|
|
102
|
+
**role** (`'user' | 'assistant' | 'system' | 'signal'`): Who produced the message. System messages and transient signals are not persisted.
|
|
103
|
+
|
|
104
|
+
**threadId** (`string`): Thread the message belongs to. Required when saving.
|
|
105
|
+
|
|
106
|
+
**resourceId** (`string`): Resource (usually a user or tenant) the message belongs to. Required when saving.
|
|
107
|
+
|
|
108
|
+
**createdAt** (`Date`): Message timestamp.
|
|
109
|
+
|
|
110
|
+
**content** (`MastraMessageContentV2`): The message body. Its parts array holds the text, reasoning, tool calls, and attachments.
|
|
111
|
+
|
|
112
|
+
`content.parts` is the part the agent actually reads. `content.format` is always `2` for stored messages, and `content.metadata` carries arbitrary custom data. `content.toolInvocations`, `content.reasoning`, and `content.experimental_attachments` are flat mirrors kept for AI SDK v4 compatibility; write to `parts` instead.
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
const assistantMessage = {
|
|
116
|
+
id: 'msg-2',
|
|
117
|
+
threadId: 'thread-123',
|
|
118
|
+
resourceId: 'user-456',
|
|
119
|
+
role: 'assistant',
|
|
120
|
+
createdAt: new Date(),
|
|
121
|
+
content: {
|
|
122
|
+
format: 2,
|
|
123
|
+
parts: [
|
|
124
|
+
{ type: 'text', text: 'It ships tomorrow.' },
|
|
125
|
+
{
|
|
126
|
+
type: 'tool-invocation',
|
|
127
|
+
toolInvocation: {
|
|
128
|
+
state: 'result',
|
|
129
|
+
toolCallId: 'call-1',
|
|
130
|
+
toolName: 'lookupOrder',
|
|
131
|
+
args: { orderId: 'A-1' },
|
|
132
|
+
result: { eta: '2026-10-30' },
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
],
|
|
136
|
+
metadata: { source: 'import' },
|
|
137
|
+
},
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
64
141
|
## Extended usage example
|
|
65
142
|
|
|
66
143
|
```typescript
|
|
@@ -251,7 +251,11 @@ const results = await pgVector.query({
|
|
|
251
251
|
})
|
|
252
252
|
```
|
|
253
253
|
|
|
254
|
-
|
|
254
|
+
With an HNSW index on pgvector 0.8.0 or newer, PostgreSQL searches the index and skips rows that don't match the filter. When the index search can't fill `topK`, pgVector reruns the query as an exact search.
|
|
255
|
+
|
|
256
|
+
With IVFFlat, or HNSW on older pgvector versions, pgVector compares the query vector against every matching row. Results are exact, but the work grows with the number of matching rows.
|
|
257
|
+
|
|
258
|
+
Indexing the metadata fields you filter on speeds up both cases and gives PostgreSQL the row counts it needs to choose between them.
|
|
255
259
|
|
|
256
260
|
### Vector Query Tool
|
|
257
261
|
|
package/dist/index.cjs
CHANGED
|
@@ -3426,10 +3426,13 @@ function rowToTask(row) {
|
|
|
3426
3426
|
suspendedAt: row.suspendedAt ? new Date(String(row.suspendedAt)) : void 0,
|
|
3427
3427
|
completedAt: row.completedAt ? new Date(String(row.completedAt)) : void 0,
|
|
3428
3428
|
ownerId: row.ownerId != null ? String(row.ownerId) : void 0,
|
|
3429
|
-
leaseExpiresAt: row.leaseExpiresAt ? new Date(String(row.leaseExpiresAt)) : void 0
|
|
3429
|
+
leaseExpiresAt: row.leaseExpiresAt ? new Date(String(row.leaseExpiresAt)) : void 0,
|
|
3430
|
+
expiresAt: row.expiresAt ? new Date(String(row.expiresAt)) : void 0,
|
|
3431
|
+
metadata: parseJson$4(row.metadata)
|
|
3430
3432
|
};
|
|
3431
3433
|
}
|
|
3432
3434
|
var BackgroundTasksLibSQL = class BackgroundTasksLibSQL extends _mastra_core_storage.BackgroundTasksStorage {
|
|
3435
|
+
supportsTaskExpiry = true;
|
|
3433
3436
|
/**
|
|
3434
3437
|
* Completed/failed task records accumulate. Anchored on `completedAt`, which
|
|
3435
3438
|
* is NULL while a task is in-flight (pending/running/suspended) — so `completedAt
|
|
@@ -3464,7 +3467,9 @@ var BackgroundTasksLibSQL = class BackgroundTasksLibSQL extends _mastra_core_sto
|
|
|
3464
3467
|
"suspend_payload",
|
|
3465
3468
|
"suspendedAt",
|
|
3466
3469
|
"ownerId",
|
|
3467
|
-
"leaseExpiresAt"
|
|
3470
|
+
"leaseExpiresAt",
|
|
3471
|
+
"expiresAt",
|
|
3472
|
+
"metadata"
|
|
3468
3473
|
]
|
|
3469
3474
|
});
|
|
3470
3475
|
}
|
|
@@ -3510,7 +3515,9 @@ var BackgroundTasksLibSQL = class BackgroundTasksLibSQL extends _mastra_core_sto
|
|
|
3510
3515
|
suspendedAt: task.suspendedAt?.toISOString() ?? null,
|
|
3511
3516
|
completedAt: task.completedAt?.toISOString() ?? null,
|
|
3512
3517
|
ownerId: task.ownerId ?? null,
|
|
3513
|
-
leaseExpiresAt: task.leaseExpiresAt?.toISOString() ?? null
|
|
3518
|
+
leaseExpiresAt: task.leaseExpiresAt?.toISOString() ?? null,
|
|
3519
|
+
expiresAt: task.expiresAt?.toISOString() ?? null,
|
|
3520
|
+
metadata: task.metadata ?? null
|
|
3514
3521
|
}
|
|
3515
3522
|
});
|
|
3516
3523
|
}
|
|
@@ -3557,6 +3564,14 @@ var BackgroundTasksLibSQL = class BackgroundTasksLibSQL extends _mastra_core_sto
|
|
|
3557
3564
|
setClauses.push("leaseExpiresAt = ?");
|
|
3558
3565
|
params.push(update.leaseExpiresAt?.toISOString() ?? null);
|
|
3559
3566
|
}
|
|
3567
|
+
if ("expiresAt" in update) {
|
|
3568
|
+
setClauses.push("expiresAt = ?");
|
|
3569
|
+
params.push(update.expiresAt?.toISOString() ?? null);
|
|
3570
|
+
}
|
|
3571
|
+
if ("metadata" in update) {
|
|
3572
|
+
setClauses.push("metadata = jsonb(?)");
|
|
3573
|
+
params.push(serializeJson(update.metadata));
|
|
3574
|
+
}
|
|
3560
3575
|
if (setClauses.length === 0) return false;
|
|
3561
3576
|
params.push(taskId);
|
|
3562
3577
|
let where = "id = ?";
|
|
@@ -3578,6 +3593,13 @@ var BackgroundTasksLibSQL = class BackgroundTasksLibSQL extends _mastra_core_sto
|
|
|
3578
3593
|
params.push(options.expectedLeaseExpiresAt.toISOString());
|
|
3579
3594
|
}
|
|
3580
3595
|
}
|
|
3596
|
+
if (options?.expectedSuspendedAt !== void 0) {
|
|
3597
|
+
if (options.expectedSuspendedAt === null) where += " AND suspendedAt IS NULL";
|
|
3598
|
+
else {
|
|
3599
|
+
where += " AND suspendedAt = ?";
|
|
3600
|
+
params.push(options.expectedSuspendedAt.toISOString());
|
|
3601
|
+
}
|
|
3602
|
+
}
|
|
3581
3603
|
return (await this.#client.execute({
|
|
3582
3604
|
sql: `UPDATE ${_mastra_core_storage.TABLE_BACKGROUND_TASKS} SET ${setClauses.join(", ")} WHERE ${where}`,
|
|
3583
3605
|
args: params
|
|
@@ -3622,7 +3644,8 @@ var BackgroundTasksLibSQL = class BackgroundTasksLibSQL extends _mastra_core_sto
|
|
|
3622
3644
|
conditions.push("tool_call_id = ?");
|
|
3623
3645
|
params.push(filter.toolCallId);
|
|
3624
3646
|
}
|
|
3625
|
-
const dateCol = filter.dateFilterBy === "startedAt" ? "startedAt" : filter.dateFilterBy === "suspendedAt" ? "suspendedAt" : filter.dateFilterBy === "completedAt" ? "completedAt" : "createdAt";
|
|
3647
|
+
const dateCol = filter.dateFilterBy === "startedAt" ? "startedAt" : filter.dateFilterBy === "suspendedAt" ? "suspendedAt" : filter.dateFilterBy === "completedAt" ? "completedAt" : filter.dateFilterBy === "expiresAt" ? "expiresAt" : "createdAt";
|
|
3648
|
+
if (filter.hasExpiresAt !== void 0) conditions.push(filter.hasExpiresAt ? "expiresAt IS NOT NULL" : "expiresAt IS NULL");
|
|
3626
3649
|
if (filter.fromDate) {
|
|
3627
3650
|
conditions.push(`${dateCol} >= ?`);
|
|
3628
3651
|
params.push(filter.fromDate.toISOString());
|
|
@@ -3670,7 +3693,8 @@ var BackgroundTasksLibSQL = class BackgroundTasksLibSQL extends _mastra_core_sto
|
|
|
3670
3693
|
conditions.push(`status IN (${statuses.map(() => "?").join(", ")})`);
|
|
3671
3694
|
params.push(...statuses);
|
|
3672
3695
|
}
|
|
3673
|
-
const dateCol = filter.dateFilterBy === "startedAt" ? "startedAt" : filter.dateFilterBy === "suspendedAt" ? "suspendedAt" : filter.dateFilterBy === "completedAt" ? "completedAt" : "createdAt";
|
|
3696
|
+
const dateCol = filter.dateFilterBy === "startedAt" ? "startedAt" : filter.dateFilterBy === "suspendedAt" ? "suspendedAt" : filter.dateFilterBy === "completedAt" ? "completedAt" : filter.dateFilterBy === "expiresAt" ? "expiresAt" : "createdAt";
|
|
3697
|
+
if (filter.hasExpiresAt !== void 0) conditions.push(filter.hasExpiresAt ? "expiresAt IS NOT NULL" : "expiresAt IS NULL");
|
|
3674
3698
|
if (filter.fromDate) {
|
|
3675
3699
|
conditions.push(`${dateCol} >= ?`);
|
|
3676
3700
|
params.push(filter.fromDate.toISOString());
|