@mastra/libsql 1.10.1-alpha.0 → 1.10.1-alpha.2
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 +30 -0
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/docs-memory-semantic-recall.md +68 -6
- package/dist/index.cjs +46 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +46 -8
- package/dist/index.js.map +1 -1
- package/dist/storage/db/utils.d.ts +11 -0
- package/dist/storage/db/utils.d.ts.map +1 -1
- package/dist/storage/domains/memory/index.d.ts +2 -1
- package/dist/storage/domains/memory/index.d.ts.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# @mastra/libsql
|
|
2
2
|
|
|
3
|
+
## 1.10.1-alpha.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- **Fixed** Workflow run snapshots no longer lose fields when serialized for storage. The libsql `safeStringify` cycle-detection treated any object that appeared more than once in a snapshot as a circular reference and dropped it. Because `snapshot.result` and the final step's `context[step].output` share the same reference on success, `snapshot.result` was being silently stripped on every persist. This caused `listWorkflowRuns` to return runs with `snapshot.result === undefined` and broke workflow resume when suspended-state fields were shared elsewhere in the snapshot. ([#16368](https://github.com/mastra-ai/mastra/pull/16368))
|
|
8
|
+
|
|
9
|
+
- Respect optional `resourceId` in `getThreadById` so scoped thread lookups return `null` when the thread belongs to a different resource. ([#14237](https://github.com/mastra-ai/mastra/pull/14237))
|
|
10
|
+
|
|
11
|
+
Example:
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
const thread = await memory.getThreadById({
|
|
15
|
+
threadId: 'my-thread-id',
|
|
16
|
+
resourceId: 'my-user-id',
|
|
17
|
+
});
|
|
18
|
+
// Returns null if the thread does not belong to 'my-user-id'.
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
- Updated dependencies [[`7c275a8`](https://github.com/mastra-ai/mastra/commit/7c275a810595e1a6c41ccc39720531ab65734700), [`890b24c`](https://github.com/mastra-ai/mastra/commit/890b24cc7d32ed6aa4dfe253e54dc6bf4099f690), [`0f48ebf`](https://github.com/mastra-ai/mastra/commit/0f48ebfc7ac7897b2092a189f45751924cf56d1c), [`f180e49`](https://github.com/mastra-ai/mastra/commit/f180e4990e71b04c9a475b523584071712f0048f), [`9260e01`](https://github.com/mastra-ai/mastra/commit/9260e015276fb1b500f7878ee452b47476bf1583), [`2f6c54e`](https://github.com/mastra-ai/mastra/commit/2f6c54e17c041cac1def54baaa6b771647836414), [`e06a159`](https://github.com/mastra-ai/mastra/commit/e06a1598ca07a6c3778aefc2a2d288363c6294ff), [`db34bc6`](https://github.com/mastra-ai/mastra/commit/db34bc6fb36cf125bda0c46be4d3fdc774b70cc4)]:
|
|
22
|
+
- @mastra/core@1.33.0-alpha.8
|
|
23
|
+
|
|
24
|
+
## 1.10.1-alpha.1
|
|
25
|
+
|
|
26
|
+
### Patch Changes
|
|
27
|
+
|
|
28
|
+
- **Fixed** Workflow runs no longer fail to persist when request context contains non-serializable values (for example functions, circular references, or platform proxy objects). This prevents errors when saving workflow snapshots and scorer results. See #12301. ([#12573](https://github.com/mastra-ai/mastra/pull/12573))
|
|
29
|
+
|
|
30
|
+
- Updated dependencies [[`6742347`](https://github.com/mastra-ai/mastra/commit/6742347d71955d7639adc9ddf6ff8282de7ee3ba), [`7b0ad1f`](https://github.com/mastra-ai/mastra/commit/7b0ad1f5c53dc118c6da12ae82ae2587037dc2b8), [`62666c3`](https://github.com/mastra-ai/mastra/commit/62666c367eaeac3941ead454b1d38810cc855721), [`4af2160`](https://github.com/mastra-ai/mastra/commit/4af2160322f4718cac421930cce85641e9512389), [`136c959`](https://github.com/mastra-ai/mastra/commit/136c9592fb0eeb0cd212f28629d8a29b7557a2fc), [`4df7cc7`](https://github.com/mastra-ai/mastra/commit/4df7cc79342fd065fe7fdeef93c094db14b12bcd), [`aca3121`](https://github.com/mastra-ai/mastra/commit/aca31211233dac25459f140ea4fcfb3a5af64c18), [`9cdf38e`](https://github.com/mastra-ai/mastra/commit/9cdf38e58506e1109c8b38f97cd7770978a4218e), [`990851e`](https://github.com/mastra-ai/mastra/commit/990851edcb0e30be5c2c18b6532f1a876cc2d335), [`6068a6c`](https://github.com/mastra-ai/mastra/commit/6068a6c42950fad3ebfc92346417896ba60803d2), [`00106be`](https://github.com/mastra-ai/mastra/commit/00106bede59b81e5b0e9cd6aad8d3b5dbc336387), [`e2a079c`](https://github.com/mastra-ai/mastra/commit/e2a079cc3755b1895f7bd5dc36e9be81b11c7c22), [`534a456`](https://github.com/mastra-ai/mastra/commit/534a456a25e4df1e5407e7e632f4cb3b1fa14f9d), [`36bae07`](https://github.com/mastra-ai/mastra/commit/36bae07c0e70b1b3006f2fd20830e8883dcbd066)]:
|
|
31
|
+
- @mastra/core@1.33.0-alpha.7
|
|
32
|
+
|
|
3
33
|
## 1.10.1-alpha.0
|
|
4
34
|
|
|
5
35
|
### Patch Changes
|
package/dist/docs/SKILL.md
CHANGED
|
@@ -121,26 +121,88 @@ Each vector store page below includes installation instructions, configuration p
|
|
|
121
121
|
|
|
122
122
|
## Recall configuration
|
|
123
123
|
|
|
124
|
-
The
|
|
124
|
+
The following options control semantic recall behavior:
|
|
125
125
|
|
|
126
|
-
1. **topK**:
|
|
127
|
-
2. **messageRange**:
|
|
128
|
-
3. **scope**: Whether to search
|
|
126
|
+
1. **topK**: The number of similar messages to retrieve
|
|
127
|
+
2. **messageRange**: The surrounding messages to include with each match
|
|
128
|
+
3. **scope**: Whether to search the current thread or all threads for a resource
|
|
129
|
+
4. **filter**: Metadata criteria that restrict search results
|
|
129
130
|
|
|
130
131
|
```typescript
|
|
131
132
|
const agent = new Agent({
|
|
132
133
|
memory: new Memory({
|
|
133
134
|
options: {
|
|
134
135
|
semanticRecall: {
|
|
135
|
-
topK: 3, // Retrieve 3
|
|
136
|
+
topK: 3, // Retrieve 3 similar messages
|
|
136
137
|
messageRange: 2, // Include 2 messages before and after each match
|
|
137
|
-
scope: 'resource', // Search
|
|
138
|
+
scope: 'resource', // Search all threads for this resource
|
|
139
|
+
filter: { projectId: { $eq: 'project-a' } },
|
|
138
140
|
},
|
|
139
141
|
},
|
|
140
142
|
}),
|
|
141
143
|
})
|
|
142
144
|
```
|
|
143
145
|
|
|
146
|
+
> **Note:** `scope: 'resource'` is supported by the LibSQL, PostgreSQL, and Upstash storage adapters.
|
|
147
|
+
|
|
148
|
+
### Metadata filtering
|
|
149
|
+
|
|
150
|
+
The `filter` option restricts semantic recall results to messages with matching thread metadata.
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
const agent = new Agent({
|
|
154
|
+
memory: new Memory({
|
|
155
|
+
options: {
|
|
156
|
+
semanticRecall: {
|
|
157
|
+
scope: 'resource',
|
|
158
|
+
filter: {
|
|
159
|
+
projectId: { $eq: 'project-a' },
|
|
160
|
+
category: { $in: ['work', 'personal'] },
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
}),
|
|
165
|
+
})
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Filters match metadata stored on message embeddings when messages are saved. If thread metadata changes later, existing embeddings keep their previous metadata until those messages are saved or indexed again.
|
|
169
|
+
|
|
170
|
+
Supported filter operators:
|
|
171
|
+
|
|
172
|
+
- `$and`: Logical AND
|
|
173
|
+
- `$eq`: Equal to
|
|
174
|
+
- `$gt`: Greater than
|
|
175
|
+
- `$gte`: Greater than or equal
|
|
176
|
+
- `$in`: In array
|
|
177
|
+
- `$lt`: Less than
|
|
178
|
+
- `$lte`: Less than or equal
|
|
179
|
+
- `$ne`: Not equal to
|
|
180
|
+
- `$nin`: Not in array
|
|
181
|
+
- `$or`: Logical OR
|
|
182
|
+
|
|
183
|
+
The following example demonstrates metadata filters for common use cases:
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
// Filter by project
|
|
187
|
+
const options = {
|
|
188
|
+
semanticRecall: { filter: { projectId: { $eq: 'my-project' } } },
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Filter by multiple categories
|
|
192
|
+
const options = {
|
|
193
|
+
semanticRecall: { filter: { category: { $in: ['work', 'research'] } } },
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Filter by project and priority
|
|
197
|
+
const options = {
|
|
198
|
+
semanticRecall: {
|
|
199
|
+
filter: {
|
|
200
|
+
$and: [{ projectId: { $eq: 'project-a' } }, { priority: { $gte: 3 } }],
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
144
206
|
## Embedder configuration
|
|
145
207
|
|
|
146
208
|
Semantic recall relies on an [embedding model](https://mastra.ai/reference/memory/memory-class) to convert messages into embeddings. Mastra supports embedding models through the model router using `provider/model` strings, or you can use any [embedding model](https://sdk.vercel.ai/docs/ai-sdk-core/embeddings) compatible with the AI SDK.
|
package/dist/index.cjs
CHANGED
|
@@ -1172,6 +1172,37 @@ var LibSQLVector = class extends vector.MastraVector {
|
|
|
1172
1172
|
});
|
|
1173
1173
|
}
|
|
1174
1174
|
};
|
|
1175
|
+
var safeStringify = (value) => {
|
|
1176
|
+
const ancestors = /* @__PURE__ */ new Set();
|
|
1177
|
+
const sanitize = (val) => {
|
|
1178
|
+
if (val === null || val === void 0) return val;
|
|
1179
|
+
if (typeof val === "function") return void 0;
|
|
1180
|
+
if (typeof val === "symbol") return void 0;
|
|
1181
|
+
if (typeof val === "bigint") return val.toString();
|
|
1182
|
+
if (typeof val !== "object") return val;
|
|
1183
|
+
if (ancestors.has(val)) return void 0;
|
|
1184
|
+
if (typeof val.toJSON === "function") {
|
|
1185
|
+
return sanitize(val.toJSON());
|
|
1186
|
+
}
|
|
1187
|
+
ancestors.add(val);
|
|
1188
|
+
try {
|
|
1189
|
+
if (Array.isArray(val)) {
|
|
1190
|
+
return val.map((item) => sanitize(item));
|
|
1191
|
+
}
|
|
1192
|
+
const result = {};
|
|
1193
|
+
for (const key of Object.keys(val)) {
|
|
1194
|
+
const sanitized = sanitize(val[key]);
|
|
1195
|
+
if (sanitized !== void 0) {
|
|
1196
|
+
result[key] = sanitized;
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
return result;
|
|
1200
|
+
} finally {
|
|
1201
|
+
ancestors.delete(val);
|
|
1202
|
+
}
|
|
1203
|
+
};
|
|
1204
|
+
return JSON.stringify(sanitize(value)) ?? "null";
|
|
1205
|
+
};
|
|
1175
1206
|
function buildSelectColumns(tableName) {
|
|
1176
1207
|
const schema = storage.TABLE_SCHEMAS[tableName];
|
|
1177
1208
|
return Object.keys(schema).map((col) => {
|
|
@@ -1238,12 +1269,12 @@ function prepareStatement({ tableName, record }) {
|
|
|
1238
1269
|
}
|
|
1239
1270
|
const colDef = schema[col];
|
|
1240
1271
|
if (colDef?.type === "jsonb") {
|
|
1241
|
-
return
|
|
1272
|
+
return safeStringify(v);
|
|
1242
1273
|
}
|
|
1243
1274
|
if (v instanceof Date) {
|
|
1244
1275
|
return v.toISOString();
|
|
1245
1276
|
}
|
|
1246
|
-
return typeof v === "object" ?
|
|
1277
|
+
return typeof v === "object" ? safeStringify(v) : v;
|
|
1247
1278
|
});
|
|
1248
1279
|
const placeholders = columnNames.map((col) => {
|
|
1249
1280
|
const colDef = schema[col];
|
|
@@ -1286,12 +1317,12 @@ function transformToSqlValue(value, forceJsonStringify = false) {
|
|
|
1286
1317
|
return null;
|
|
1287
1318
|
}
|
|
1288
1319
|
if (forceJsonStringify) {
|
|
1289
|
-
return
|
|
1320
|
+
return safeStringify(value);
|
|
1290
1321
|
}
|
|
1291
1322
|
if (value instanceof Date) {
|
|
1292
1323
|
return value.toISOString();
|
|
1293
1324
|
}
|
|
1294
|
-
return typeof value === "object" ?
|
|
1325
|
+
return typeof value === "object" ? safeStringify(value) : value;
|
|
1295
1326
|
}
|
|
1296
1327
|
function prepareDeleteStatement({ tableName, keys }) {
|
|
1297
1328
|
const parsedTableName = utils.parseSqlIdentifier(tableName, "table name");
|
|
@@ -6609,11 +6640,18 @@ var MemoryLibSQL = class extends storage.MemoryStorage {
|
|
|
6609
6640
|
});
|
|
6610
6641
|
return updatedResource;
|
|
6611
6642
|
}
|
|
6612
|
-
async getThreadById({
|
|
6643
|
+
async getThreadById({
|
|
6644
|
+
threadId,
|
|
6645
|
+
resourceId
|
|
6646
|
+
}) {
|
|
6613
6647
|
try {
|
|
6648
|
+
const keys = { id: threadId };
|
|
6649
|
+
if (resourceId !== void 0) {
|
|
6650
|
+
keys.resourceId = resourceId;
|
|
6651
|
+
}
|
|
6614
6652
|
const result = await this.#db.select({
|
|
6615
6653
|
tableName: storage.TABLE_THREADS,
|
|
6616
|
-
keys
|
|
6654
|
+
keys
|
|
6617
6655
|
});
|
|
6618
6656
|
if (!result) {
|
|
6619
6657
|
return null;
|
|
@@ -10607,7 +10645,7 @@ var WorkflowsLibSQL = class extends storage.WorkflowsStorage {
|
|
|
10607
10645
|
VALUES (?, ?, jsonb(?), ?, ?)
|
|
10608
10646
|
ON CONFLICT(workflow_name, run_id)
|
|
10609
10647
|
DO UPDATE SET snapshot = excluded.snapshot, updatedAt = excluded.updatedAt`,
|
|
10610
|
-
args: [workflowName, runId,
|
|
10648
|
+
args: [workflowName, runId, safeStringify(snapshot), now, now]
|
|
10611
10649
|
});
|
|
10612
10650
|
await tx.commit();
|
|
10613
10651
|
return snapshot.context;
|
|
@@ -10644,7 +10682,7 @@ var WorkflowsLibSQL = class extends storage.WorkflowsStorage {
|
|
|
10644
10682
|
const updatedSnapshot = { ...snapshot, ...opts };
|
|
10645
10683
|
await tx.execute({
|
|
10646
10684
|
sql: `UPDATE ${storage.TABLE_WORKFLOW_SNAPSHOT} SET snapshot = jsonb(?) WHERE workflow_name = ? AND run_id = ?`,
|
|
10647
|
-
args: [
|
|
10685
|
+
args: [safeStringify(updatedSnapshot), workflowName, runId]
|
|
10648
10686
|
});
|
|
10649
10687
|
await tx.commit();
|
|
10650
10688
|
return updatedSnapshot;
|