@mastra/libsql 1.17.1-alpha.1 → 1.18.0-alpha.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/CHANGELOG.md +36 -0
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/docs-memory-message-history.md +18 -0
- package/dist/index.cjs +40 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +41 -2
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/memory/index.d.ts.map +1 -1
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
# @mastra/libsql
|
|
2
2
|
|
|
3
|
+
## 1.18.0-alpha.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Added exact metadata filtering to message history queries across Memory APIs and supported storage providers. ([#19991](https://github.com/mastra-ai/mastra/pull/19991))
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
const messages = await memory.recall({
|
|
11
|
+
threadId: 'thread-1',
|
|
12
|
+
filter: {
|
|
13
|
+
metadata: {
|
|
14
|
+
status: 'done',
|
|
15
|
+
priority: 'high',
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Multiple fields use AND semantics. Supported values are strings, finite numbers, booleans, and `null`.
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- Updated dependencies [[`0dca9d0`](https://github.com/mastra-ai/mastra/commit/0dca9d0b1356024a53b72ea6f040db528b126caa)]:
|
|
26
|
+
- @mastra/core@1.54.0-alpha.0
|
|
27
|
+
|
|
28
|
+
## 1.17.1
|
|
29
|
+
|
|
30
|
+
### Patch Changes
|
|
31
|
+
|
|
32
|
+
- Fixed data loss and corruption in observational memory when it is written to concurrently on a local SQLite database. Buffered observations could previously be dropped or leave the memory record in an inconsistent state under load; memory updates are now serialized so concurrent writes are preserved. ([#20110](https://github.com/mastra-ai/mastra/pull/20110))
|
|
33
|
+
|
|
34
|
+
- Fixed local LibSQL stores changing shared database journal state when they close. ([#20227](https://github.com/mastra-ai/mastra/pull/20227))
|
|
35
|
+
|
|
36
|
+
- Updated dependencies [[`c8d8a01`](https://github.com/mastra-ai/mastra/commit/c8d8a010ee2efe2b7bf4d07707382c34c87b14e4), [`df6a9ce`](https://github.com/mastra-ai/mastra/commit/df6a9ce87214f7aadb2edfe62f67605fe998a0a4), [`73839cb`](https://github.com/mastra-ai/mastra/commit/73839cb58322679c170627d1015669ede5f619aa), [`371cf60`](https://github.com/mastra-ai/mastra/commit/371cf6075cef88ac6919a08d59a82e485397364a), [`8e4dc79`](https://github.com/mastra-ai/mastra/commit/8e4dc793dcf035ea506f9ce79f56d2d501a4be14), [`2db93cc`](https://github.com/mastra-ai/mastra/commit/2db93ccd0b872e4de7853a93383efe0647901df8), [`094ab61`](https://github.com/mastra-ai/mastra/commit/094ab6129a1a3ecf6eeb86decac17d5faea4e02a), [`fe80944`](https://github.com/mastra-ai/mastra/commit/fe80944f3ef6681fea6eae8200fce387b7bb3c2f), [`263d2ca`](https://github.com/mastra-ai/mastra/commit/263d2cac80ba3b03b9c0f008db6f1f1b9eb0278c), [`75f843d`](https://github.com/mastra-ai/mastra/commit/75f843d09f758223e6eeb321321bdcc5c7e779d0), [`e51e166`](https://github.com/mastra-ai/mastra/commit/e51e166c52e220abc9b64554ce37359dca8544b1)]:
|
|
37
|
+
- @mastra/core@1.53.0
|
|
38
|
+
|
|
3
39
|
## 1.17.1-alpha.1
|
|
4
40
|
|
|
5
41
|
### Patch Changes
|
package/dist/docs/SKILL.md
CHANGED
|
@@ -263,6 +263,24 @@ const { messages } = await memory.recall({
|
|
|
263
263
|
})
|
|
264
264
|
```
|
|
265
265
|
|
|
266
|
+
Filter by shallow message metadata:
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
const { messages } = await memory.recall({
|
|
270
|
+
threadId: 'thread-123',
|
|
271
|
+
filter: {
|
|
272
|
+
metadata: {
|
|
273
|
+
category: 'billing',
|
|
274
|
+
escalated: true,
|
|
275
|
+
priority: 2,
|
|
276
|
+
archivedAt: null,
|
|
277
|
+
},
|
|
278
|
+
},
|
|
279
|
+
})
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
Metadata filters match shallow scalar values only: `string`, finite `number`, `boolean`, and `null`. All specified metadata keys must match with AND semantics, and `null` matches an explicit `null` value, not a missing metadata key. Metadata keys must start with a letter or underscore, may contain only alphanumeric characters and underscores, must be 128 characters or fewer, and can't use reserved prototype keys such as `__proto__`, `constructor`, or `prototype`. Performance depends on the storage backend. Some backends can push parts of the filter into the database, while others scan candidate messages after thread, resource, and date constraints are applied but before pagination.
|
|
283
|
+
|
|
266
284
|
Fetch a single message by ID:
|
|
267
285
|
|
|
268
286
|
```typescript
|
package/dist/index.cjs
CHANGED
|
@@ -7008,6 +7008,40 @@ var MCPServersLibSQL = class extends storage.MCPServersStorage {
|
|
|
7008
7008
|
}
|
|
7009
7009
|
};
|
|
7010
7010
|
var OM_TABLE = "mastra_observational_memory";
|
|
7011
|
+
function addSqliteMetadataFilter(conditions, params, metadataFilter) {
|
|
7012
|
+
if (!metadataFilter) return;
|
|
7013
|
+
for (const [key, value] of Object.entries(metadataFilter)) {
|
|
7014
|
+
const path = `$.metadata.${key}`;
|
|
7015
|
+
conditions.push(`CASE WHEN json_valid(content) THEN json_type(content, ?) IS NOT NULL ELSE 0 END`);
|
|
7016
|
+
params.push(path);
|
|
7017
|
+
addSqliteMetadataValuePredicate(conditions, params, path, value);
|
|
7018
|
+
}
|
|
7019
|
+
}
|
|
7020
|
+
function addSqliteMetadataValuePredicate(conditions, params, path, value) {
|
|
7021
|
+
if (value === null) {
|
|
7022
|
+
conditions.push(`CASE WHEN json_valid(content) THEN json_type(content, ?) = 'null' ELSE 0 END`);
|
|
7023
|
+
params.push(path);
|
|
7024
|
+
return;
|
|
7025
|
+
}
|
|
7026
|
+
if (typeof value === "string") {
|
|
7027
|
+
conditions.push(
|
|
7028
|
+
`CASE WHEN json_valid(content) THEN json_type(content, ?) = 'text' AND json_extract(content, ?) = ? ELSE 0 END`
|
|
7029
|
+
);
|
|
7030
|
+
params.push(path, path, value);
|
|
7031
|
+
return;
|
|
7032
|
+
}
|
|
7033
|
+
if (typeof value === "number") {
|
|
7034
|
+
conditions.push(
|
|
7035
|
+
`CASE WHEN json_valid(content) THEN json_type(content, ?) IN ('integer', 'real') AND json_extract(content, ?) = ? ELSE 0 END`
|
|
7036
|
+
);
|
|
7037
|
+
params.push(path, path, value);
|
|
7038
|
+
return;
|
|
7039
|
+
}
|
|
7040
|
+
conditions.push(
|
|
7041
|
+
`CASE WHEN json_valid(content) THEN json_type(content, ?) = ? AND json_extract(content, ?) = ? ELSE 0 END`
|
|
7042
|
+
);
|
|
7043
|
+
params.push(path, value ? "true" : "false", path, value ? 1 : 0);
|
|
7044
|
+
}
|
|
7011
7045
|
var MemoryLibSQL = class _MemoryLibSQL extends storage.MemoryStorage {
|
|
7012
7046
|
supportsObservationalMemory = true;
|
|
7013
7047
|
/**
|
|
@@ -7253,6 +7287,7 @@ var MemoryLibSQL = class _MemoryLibSQL extends storage.MemoryStorage {
|
|
|
7253
7287
|
}
|
|
7254
7288
|
const perPage = storage.normalizePerPage(perPageInput, 40);
|
|
7255
7289
|
const { offset, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
7290
|
+
const metadataFilter = storage.validateStorageMetadataFilter(filter?.metadata);
|
|
7256
7291
|
try {
|
|
7257
7292
|
const { field, direction } = this.parseOrderBy(orderBy, "ASC");
|
|
7258
7293
|
const orderByStatement = `ORDER BY "${field}" ${direction}`;
|
|
@@ -7277,6 +7312,7 @@ var MemoryLibSQL = class _MemoryLibSQL extends storage.MemoryStorage {
|
|
|
7277
7312
|
filter.dateRange.end instanceof Date ? filter.dateRange.end.toISOString() : filter.dateRange.end
|
|
7278
7313
|
);
|
|
7279
7314
|
}
|
|
7315
|
+
addSqliteMetadataFilter(conditions, queryParams, metadataFilter);
|
|
7280
7316
|
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
7281
7317
|
if (perPage === 0 && (!include || include.length === 0)) {
|
|
7282
7318
|
return { messages: [], total: 0, page, perPage: perPageForResponse, hasMore: false };
|
|
@@ -7306,6 +7342,7 @@ var MemoryLibSQL = class _MemoryLibSQL extends storage.MemoryStorage {
|
|
|
7306
7342
|
args: [...queryParams, limitValue, offset]
|
|
7307
7343
|
});
|
|
7308
7344
|
const messages = (dataResult.rows || []).map((row) => this.parseRow(row));
|
|
7345
|
+
const paginatedCount = messages.length;
|
|
7309
7346
|
if (total === 0 && messages.length === 0 && (!include || include.length === 0)) {
|
|
7310
7347
|
return {
|
|
7311
7348
|
messages: [],
|
|
@@ -7334,7 +7371,7 @@ var MemoryLibSQL = class _MemoryLibSQL extends storage.MemoryStorage {
|
|
|
7334
7371
|
finalMessages.filter((m) => m.threadId && threadIdSet.has(m.threadId)).map((m) => m.id)
|
|
7335
7372
|
);
|
|
7336
7373
|
const allThreadMessagesReturned = returnedThreadMessageIds.size >= total;
|
|
7337
|
-
const hasMore = perPageInput !== false && !allThreadMessagesReturned && offset + perPage < total;
|
|
7374
|
+
const hasMore = metadataFilter ? perPageInput !== false && offset + paginatedCount < total : perPageInput !== false && !allThreadMessagesReturned && offset + perPage < total;
|
|
7338
7375
|
return {
|
|
7339
7376
|
messages: finalMessages,
|
|
7340
7377
|
total,
|
|
@@ -7392,6 +7429,7 @@ var MemoryLibSQL = class _MemoryLibSQL extends storage.MemoryStorage {
|
|
|
7392
7429
|
}
|
|
7393
7430
|
const perPage = storage.normalizePerPage(perPageInput, 40);
|
|
7394
7431
|
const { offset, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
7432
|
+
const metadataFilter = storage.validateStorageMetadataFilter(filter?.metadata);
|
|
7395
7433
|
try {
|
|
7396
7434
|
const { field, direction } = this.parseOrderBy(orderBy, "ASC");
|
|
7397
7435
|
const orderByStatement = `ORDER BY "${field}" ${direction}`;
|
|
@@ -7413,6 +7451,7 @@ var MemoryLibSQL = class _MemoryLibSQL extends storage.MemoryStorage {
|
|
|
7413
7451
|
filter.dateRange.end instanceof Date ? filter.dateRange.end.toISOString() : filter.dateRange.end
|
|
7414
7452
|
);
|
|
7415
7453
|
}
|
|
7454
|
+
addSqliteMetadataFilter(conditions, queryParams, metadataFilter);
|
|
7416
7455
|
const whereClause = `WHERE ${conditions.join(" AND ")}`;
|
|
7417
7456
|
if (perPage === 0 && (!include || include.length === 0)) {
|
|
7418
7457
|
return { messages: [], total: 0, page, perPage: perPageForResponse, hasMore: false };
|