@mastra/libsql 1.17.1-alpha.0 → 1.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -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 +19 -1
- package/dist/docs/references/reference-memory-memory-class.md +1 -1
- package/dist/index.cjs +46 -40
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +47 -41
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/memory/index.d.ts.map +1 -1
- package/dist/storage/factory-storage.d.ts +0 -3
- package/dist/storage/factory-storage.d.ts.map +1 -1
- package/dist/storage/index.d.ts +1 -9
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/vector/index.d.ts +1 -7
- package/dist/vector/index.d.ts.map +1 -1
- package/dist/vector/sql-builder.d.ts.map +1 -1
- package/package.json +7 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# @mastra/libsql
|
|
2
2
|
|
|
3
|
+
## 1.17.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 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))
|
|
8
|
+
|
|
9
|
+
- Fixed local LibSQL stores changing shared database journal state when they close. ([#20227](https://github.com/mastra-ai/mastra/pull/20227))
|
|
10
|
+
|
|
11
|
+
- 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)]:
|
|
12
|
+
- @mastra/core@1.53.0
|
|
13
|
+
|
|
14
|
+
## 1.17.1-alpha.1
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- Fixed local LibSQL stores changing shared database journal state when they close. ([#20227](https://github.com/mastra-ai/mastra/pull/20227))
|
|
19
|
+
|
|
20
|
+
- Updated dependencies [[`73839cb`](https://github.com/mastra-ai/mastra/commit/73839cb58322679c170627d1015669ede5f619aa), [`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), [`e51e166`](https://github.com/mastra-ai/mastra/commit/e51e166c52e220abc9b64554ce37359dca8544b1)]:
|
|
21
|
+
- @mastra/core@1.53.0-alpha.4
|
|
22
|
+
|
|
3
23
|
## 1.17.1-alpha.0
|
|
4
24
|
|
|
5
25
|
### Patch Changes
|
package/dist/docs/SKILL.md
CHANGED
|
@@ -124,7 +124,7 @@ You can use this history in two ways:
|
|
|
124
124
|
|
|
125
125
|
## Thread title generation
|
|
126
126
|
|
|
127
|
-
Mastra can automatically generate descriptive thread titles
|
|
127
|
+
Mastra can automatically generate descriptive thread titles from the conversation transcript when `generateTitle` is enabled. Use this option when you build a chat interface that renders conversation titles in a thread list or sidebar.
|
|
128
128
|
|
|
129
129
|
```typescript
|
|
130
130
|
import { Agent } from '@mastra/core/agent'
|
|
@@ -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
|
|
@@ -47,7 +47,7 @@ export const agent = new Agent({
|
|
|
47
47
|
|
|
48
48
|
**options.observationalMemory** (`boolean | ObservationalMemoryOptions`): Enable Observational Memory for long-context agentic memory. Set to true for defaults, or pass a config object to customize token budgets, models, and scope. See Observational Memory reference for configuration details.
|
|
49
49
|
|
|
50
|
-
**options.generateTitle** (`boolean | { model: DynamicArgument<MastraLanguageModel>; instructions?: DynamicArgument<string> }`): Controls automatic thread title generation from the
|
|
50
|
+
**options.generateTitle** (`boolean | { model: DynamicArgument<MastraLanguageModel>; instructions?: DynamicArgument<string> }`): Controls automatic thread title generation from the conversation transcript. Can be a boolean or an object with custom model and instructions.
|
|
51
51
|
|
|
52
52
|
## Returns
|
|
53
53
|
|
package/dist/index.cjs
CHANGED
|
@@ -546,29 +546,14 @@ var LibSQLVector = class extends vector.MastraVector {
|
|
|
546
546
|
this.vectorIndexes = this.isMemoryDb ? Promise.resolve(/* @__PURE__ */ new Set()) : this.discoverVectorIndexes();
|
|
547
547
|
}
|
|
548
548
|
/**
|
|
549
|
-
* Closes the underlying libsql client, releasing
|
|
550
|
-
*
|
|
551
|
-
* For local file databases, first runs PRAGMA wal_checkpoint(TRUNCATE) and
|
|
552
|
-
* switches back to journal_mode=DELETE so the -wal and -shm sidecar files
|
|
553
|
-
* are released promptly (mirrors LibSQLStore.close()).
|
|
554
|
-
*
|
|
555
|
-
* Remote (Turso) databases skip the WAL pragmas and just close the client.
|
|
549
|
+
* Closes the underlying libsql client, releasing this vector store's OS file handles.
|
|
556
550
|
*
|
|
557
551
|
* Safe to call more than once; subsequent calls are no-ops.
|
|
558
552
|
*/
|
|
559
553
|
async close() {
|
|
560
|
-
if (this.turso.closed) {
|
|
561
|
-
|
|
562
|
-
}
|
|
563
|
-
if (this.turso.protocol === "file" && !this.isMemoryDb) {
|
|
564
|
-
try {
|
|
565
|
-
await this.turso.execute("PRAGMA wal_checkpoint(TRUNCATE);");
|
|
566
|
-
await this.turso.execute("PRAGMA journal_mode=DELETE;");
|
|
567
|
-
} catch (err) {
|
|
568
|
-
this.logger.warn("LibSQLVector: Failed to checkpoint WAL before close.", err);
|
|
569
|
-
}
|
|
554
|
+
if (!this.turso.closed) {
|
|
555
|
+
this.turso.close();
|
|
570
556
|
}
|
|
571
|
-
this.turso.close();
|
|
572
557
|
}
|
|
573
558
|
async discoverVectorIndexes() {
|
|
574
559
|
try {
|
|
@@ -7023,6 +7008,40 @@ var MCPServersLibSQL = class extends storage.MCPServersStorage {
|
|
|
7023
7008
|
}
|
|
7024
7009
|
};
|
|
7025
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
|
+
}
|
|
7026
7045
|
var MemoryLibSQL = class _MemoryLibSQL extends storage.MemoryStorage {
|
|
7027
7046
|
supportsObservationalMemory = true;
|
|
7028
7047
|
/**
|
|
@@ -7268,6 +7287,7 @@ var MemoryLibSQL = class _MemoryLibSQL extends storage.MemoryStorage {
|
|
|
7268
7287
|
}
|
|
7269
7288
|
const perPage = storage.normalizePerPage(perPageInput, 40);
|
|
7270
7289
|
const { offset, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
7290
|
+
const metadataFilter = storage.validateStorageMetadataFilter(filter?.metadata);
|
|
7271
7291
|
try {
|
|
7272
7292
|
const { field, direction } = this.parseOrderBy(orderBy, "ASC");
|
|
7273
7293
|
const orderByStatement = `ORDER BY "${field}" ${direction}`;
|
|
@@ -7292,6 +7312,7 @@ var MemoryLibSQL = class _MemoryLibSQL extends storage.MemoryStorage {
|
|
|
7292
7312
|
filter.dateRange.end instanceof Date ? filter.dateRange.end.toISOString() : filter.dateRange.end
|
|
7293
7313
|
);
|
|
7294
7314
|
}
|
|
7315
|
+
addSqliteMetadataFilter(conditions, queryParams, metadataFilter);
|
|
7295
7316
|
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
7296
7317
|
if (perPage === 0 && (!include || include.length === 0)) {
|
|
7297
7318
|
return { messages: [], total: 0, page, perPage: perPageForResponse, hasMore: false };
|
|
@@ -7321,6 +7342,7 @@ var MemoryLibSQL = class _MemoryLibSQL extends storage.MemoryStorage {
|
|
|
7321
7342
|
args: [...queryParams, limitValue, offset]
|
|
7322
7343
|
});
|
|
7323
7344
|
const messages = (dataResult.rows || []).map((row) => this.parseRow(row));
|
|
7345
|
+
const paginatedCount = messages.length;
|
|
7324
7346
|
if (total === 0 && messages.length === 0 && (!include || include.length === 0)) {
|
|
7325
7347
|
return {
|
|
7326
7348
|
messages: [],
|
|
@@ -7349,7 +7371,7 @@ var MemoryLibSQL = class _MemoryLibSQL extends storage.MemoryStorage {
|
|
|
7349
7371
|
finalMessages.filter((m) => m.threadId && threadIdSet.has(m.threadId)).map((m) => m.id)
|
|
7350
7372
|
);
|
|
7351
7373
|
const allThreadMessagesReturned = returnedThreadMessageIds.size >= total;
|
|
7352
|
-
const hasMore = perPageInput !== false && !allThreadMessagesReturned && offset + perPage < total;
|
|
7374
|
+
const hasMore = metadataFilter ? perPageInput !== false && offset + paginatedCount < total : perPageInput !== false && !allThreadMessagesReturned && offset + perPage < total;
|
|
7353
7375
|
return {
|
|
7354
7376
|
messages: finalMessages,
|
|
7355
7377
|
total,
|
|
@@ -7407,6 +7429,7 @@ var MemoryLibSQL = class _MemoryLibSQL extends storage.MemoryStorage {
|
|
|
7407
7429
|
}
|
|
7408
7430
|
const perPage = storage.normalizePerPage(perPageInput, 40);
|
|
7409
7431
|
const { offset, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
7432
|
+
const metadataFilter = storage.validateStorageMetadataFilter(filter?.metadata);
|
|
7410
7433
|
try {
|
|
7411
7434
|
const { field, direction } = this.parseOrderBy(orderBy, "ASC");
|
|
7412
7435
|
const orderByStatement = `ORDER BY "${field}" ${direction}`;
|
|
@@ -7428,6 +7451,7 @@ var MemoryLibSQL = class _MemoryLibSQL extends storage.MemoryStorage {
|
|
|
7428
7451
|
filter.dateRange.end instanceof Date ? filter.dateRange.end.toISOString() : filter.dateRange.end
|
|
7429
7452
|
);
|
|
7430
7453
|
}
|
|
7454
|
+
addSqliteMetadataFilter(conditions, queryParams, metadataFilter);
|
|
7431
7455
|
const whereClause = `WHERE ${conditions.join(" AND ")}`;
|
|
7432
7456
|
if (perPage === 0 && (!include || include.length === 0)) {
|
|
7433
7457
|
return { messages: [], total: 0, page, perPage: perPageForResponse, hasMore: false };
|
|
@@ -14018,32 +14042,14 @@ var LibSQLStore = class extends storage.MastraCompositeStore {
|
|
|
14018
14042
|
await this.initDomainsSequentially();
|
|
14019
14043
|
}
|
|
14020
14044
|
/**
|
|
14021
|
-
* Closes the underlying libsql client, releasing
|
|
14022
|
-
*
|
|
14023
|
-
* For local file databases, first runs PRAGMA wal_checkpoint(TRUNCATE) and
|
|
14024
|
-
* switches back to journal_mode=DELETE so that Windows releases the -wal
|
|
14025
|
-
* and -shm sidecar files promptly. Without this, the handles stay open
|
|
14026
|
-
* until process exit, causing EBUSY errors when callers try to fs.rm the
|
|
14027
|
-
* storage directory after Mastra.shutdown().
|
|
14028
|
-
*
|
|
14029
|
-
* Remote (Turso) databases skip the WAL pragmas and just close the client.
|
|
14045
|
+
* Closes the underlying libsql client, releasing this store's OS file handles.
|
|
14030
14046
|
*
|
|
14031
14047
|
* Safe to call more than once; subsequent calls are no-ops.
|
|
14032
14048
|
*/
|
|
14033
14049
|
async close() {
|
|
14034
|
-
if (this.client.closed) {
|
|
14035
|
-
|
|
14036
|
-
}
|
|
14037
|
-
const isLocalFileDb = this.isLocalDb || this.client.protocol === "file";
|
|
14038
|
-
if (isLocalFileDb) {
|
|
14039
|
-
try {
|
|
14040
|
-
await this.client.execute("PRAGMA wal_checkpoint(TRUNCATE);");
|
|
14041
|
-
await this.client.execute("PRAGMA journal_mode=DELETE;");
|
|
14042
|
-
} catch (err) {
|
|
14043
|
-
this.logger.warn("LibSQLStore: Failed to checkpoint WAL before close.", err);
|
|
14044
|
-
}
|
|
14050
|
+
if (!this.client.closed) {
|
|
14051
|
+
this.client.close();
|
|
14045
14052
|
}
|
|
14046
|
-
this.client.close();
|
|
14047
14053
|
}
|
|
14048
14054
|
};
|
|
14049
14055
|
|