@mastra/libsql 1.17.1-alpha.1 → 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 CHANGED
@@ -1,5 +1,16 @@
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
+
3
14
  ## 1.17.1-alpha.1
4
15
 
5
16
  ### Patch Changes
@@ -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.17.1-alpha.1"
6
+ version: "1.17.1"
7
7
  ---
8
8
 
9
9
  ## When to use
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.17.1-alpha.1",
2
+ "version": "1.17.1",
3
3
  "package": "@mastra/libsql",
4
4
  "exports": {},
5
5
  "modules": {}
@@ -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 };