@mastra/libsql 1.20.0-alpha.0 → 1.20.0-alpha.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,22 @@
1
1
  # @mastra/libsql
2
2
 
3
+ ## 1.20.0-alpha.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Fixed `include` in `listMessages` and `listMessagesByResourceId` so it can no longer return a message that belongs to a different resource. When you pass a `resourceId`, the target message and its surrounding context messages now stay inside that resource. Includes that cross threads inside the same resource keep working, so semantic recall with `scope: 'resource'` is unchanged. ([#20984](https://github.com/mastra-ai/mastra/pull/20984))
8
+
9
+ **Behaviour change in the in-memory store**
10
+
11
+ The in-memory store read the context window from the thread you queried. It now reads the window from the thread that owns the target message, which is what the SQL stores already did. This only changes the result when an `include` entry names a message from another thread.
12
+
13
+ The in-memory store also ignored `include` in `listMessagesByResourceId`. It now returns the included messages, like `@mastra/libsql` and `@mastra/pg` do.
14
+
15
+ Fixes #20604.
16
+
17
+ - Updated dependencies [[`6445eba`](https://github.com/mastra-ai/mastra/commit/6445eba6020abac681aba1cc9289f446cb400cbe), [`df31eb0`](https://github.com/mastra-ai/mastra/commit/df31eb0c7087d782a0d9346e467f9a4af4b0eef6), [`fcd0667`](https://github.com/mastra-ai/mastra/commit/fcd0667a4e378be35c9a1b1eb19cce78fbfd7282), [`bab06b1`](https://github.com/mastra-ai/mastra/commit/bab06b18923873a584bdfc71a6b4ec7fb4727fb7)]:
18
+ - @mastra/core@1.58.0-alpha.5
19
+
3
20
  ## 1.20.0-alpha.0
4
21
 
5
22
  ### Minor 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.20.0-alpha.0"
6
+ version: "1.20.0-alpha.1"
7
7
  ---
8
8
 
9
9
  ## When to use
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.20.0-alpha.0",
2
+ "version": "1.20.0-alpha.1",
3
3
  "package": "@mastra/libsql",
4
4
  "exports": {},
5
5
  "modules": {}
@@ -251,6 +251,64 @@ const memoryStore = await storage.getStore('memory')
251
251
  const thread = await memoryStore?.getThreadById({ threadId: '...' })
252
252
  ```
253
253
 
254
+ ## Closing connections
255
+
256
+ `close()` releases the connections of the stores a composite was built from: the `default` and `editor` stores, plus any domain that owns its own client. Each store is closed once, even when it backs several domains. When passed to the Mastra class, `close()` is called by `shutdown()`:
257
+
258
+ ```typescript
259
+ import { MastraCompositeStore } from '@mastra/core/storage'
260
+ import { PostgresStore } from '@mastra/pg'
261
+ import { Mastra } from '@mastra/core'
262
+
263
+ const pgStore = new PostgresStore({
264
+ id: 'pg-storage',
265
+ connectionString: process.env.DATABASE_URL,
266
+ })
267
+
268
+ export const mastra = new Mastra({
269
+ storage: new MastraCompositeStore({ id: 'composite', default: pgStore }),
270
+ })
271
+
272
+ process.on('SIGTERM', async () => {
273
+ // Releases the Postgres pool, so the process can exit
274
+ await mastra.shutdown()
275
+ })
276
+ ```
277
+
278
+ A store you construct only to supply a domain isn't reachable through the composite. Keep a reference to it and close it yourself:
279
+
280
+ ```typescript
281
+ import { MastraCompositeStore } from '@mastra/core/storage'
282
+ import { ClickhouseStore } from '@mastra/clickhouse'
283
+ import { PostgresStore } from '@mastra/pg'
284
+ import { Mastra } from '@mastra/core'
285
+
286
+ const pgStore = new PostgresStore({
287
+ id: 'pg-storage',
288
+ connectionString: process.env.DATABASE_URL,
289
+ })
290
+
291
+ const clickhouseStore = new ClickhouseStore({
292
+ id: 'clickhouse-storage',
293
+ url: process.env.CLICKHOUSE_URL,
294
+ username: process.env.CLICKHOUSE_USERNAME,
295
+ password: process.env.CLICKHOUSE_PASSWORD,
296
+ })
297
+
298
+ export const mastra = new Mastra({
299
+ storage: new MastraCompositeStore({
300
+ id: 'composite',
301
+ default: pgStore,
302
+ domains: { observability: clickhouseStore.stores?.observability },
303
+ }),
304
+ })
305
+
306
+ process.on('SIGTERM', async () => {
307
+ await mastra.shutdown()
308
+ await clickhouseStore.close()
309
+ })
310
+ ```
311
+
254
312
  ## Use cases
255
313
 
256
314
  ### Separate databases for different workloads
@@ -92,7 +92,7 @@ Each domain declares which of its tables can be age-pruned and which timestamp c
92
92
  > - Experiments prune as whole units: an aged experiment's result rows are deleted together with it (results cascade with their parent), so a run is never left partially deleted. Retention doesn't have a separate `results` key.
93
93
  > - For `schedules`, the growth table is the fire history (`schedule_triggers`, one row per fire): schedule definitions are config and aren't pruned.
94
94
  > - On PostgreSQL, timestamp anchors use the timezone-aware mirror columns (for example `createdAtZ`, `completedAtZ`).
95
- > - LibSQL supports all domains above; PostgreSQL and MongoDB support all except `threadState` and `harness`, which they don't implement.
95
+ > - LibSQL and PostgreSQL support all domains above except `harness`, which PostgreSQL doesn't implement. MongoDB supports all except `threadState` and `harness`.
96
96
  > - The v-next PostgreSQL observability domain stores signal events in day-partitioned tables (`spans`, `metrics`, `logs`, `scores`, `feedback`). For it, `prune()` drops whole day partitions (or TimescaleDB chunks) that are entirely older than the cutoff instead of deleting rows: effective level of detail is one day, and a partition is only dropped once its entire day is past `maxAge`. `PruneResult.deleted` reports the number of rows in the dropped partitions.
97
97
 
98
98
  ## Methods
package/dist/index.cjs CHANGED
@@ -6722,14 +6722,21 @@ var MemoryLibSQL = class MemoryLibSQL extends _mastra_core_storage.MemoryStorage
6722
6722
  return direction === "ASC" ? String(aValue).localeCompare(String(bValue)) : String(bValue).localeCompare(String(aValue));
6723
6723
  });
6724
6724
  }
6725
- async _getIncludedMessages({ include }) {
6725
+ /**
6726
+ * Fetches included messages by ID, discovering their thread automatically.
6727
+ * This handles cross-thread includes where the include item doesn't specify a threadId.
6728
+ * When a resourceId is given, both the target lookup and the surrounding window stay
6729
+ * inside that resource, so an include never leaks another resource's messages.
6730
+ */
6731
+ async _getIncludedMessages({ include, resourceId }) {
6726
6732
  if (!include || include.length === 0) return null;
6727
6733
  const targetIds = include.map((inc) => inc.id).filter(Boolean);
6728
6734
  if (targetIds.length === 0) return null;
6735
+ const resourceCondition = resourceId ? ` AND "resourceId" = ?` : "";
6729
6736
  const idPlaceholders = targetIds.map(() => "?").join(", ");
6730
6737
  const targetResult = await this.#client.execute({
6731
- sql: `SELECT id, thread_id, "createdAt" FROM "${_mastra_core_storage.TABLE_MESSAGES}" WHERE id IN (${idPlaceholders})`,
6732
- args: targetIds
6738
+ sql: `SELECT id, thread_id, "createdAt" FROM "${_mastra_core_storage.TABLE_MESSAGES}" WHERE id IN (${idPlaceholders})${resourceCondition}`,
6739
+ args: resourceId ? [...targetIds, resourceId] : targetIds
6733
6740
  });
6734
6741
  if (!targetResult.rows || targetResult.rows.length === 0) return null;
6735
6742
  const targetMap = new Map(targetResult.rows.map((r) => [r.id, {
@@ -6746,21 +6753,25 @@ var MemoryLibSQL = class MemoryLibSQL extends _mastra_core_storage.MemoryStorage
6746
6753
  SELECT id, content, role, type, "createdAt", thread_id, "resourceId"
6747
6754
  FROM "${_mastra_core_storage.TABLE_MESSAGES}"
6748
6755
  WHERE thread_id = ?
6749
- AND "createdAt" <= ?
6756
+ AND "createdAt" <= ?${resourceCondition}
6750
6757
  ORDER BY "createdAt" DESC, id DESC
6751
6758
  LIMIT ?
6752
6759
  )`);
6753
- params.push(target.threadId, target.createdAt, withPreviousMessages + 1);
6760
+ params.push(target.threadId, target.createdAt);
6761
+ if (resourceId) params.push(resourceId);
6762
+ params.push(withPreviousMessages + 1);
6754
6763
  if (withNextMessages > 0) {
6755
6764
  unionQueries.push(`SELECT * FROM (
6756
6765
  SELECT id, content, role, type, "createdAt", thread_id, "resourceId"
6757
6766
  FROM "${_mastra_core_storage.TABLE_MESSAGES}"
6758
6767
  WHERE thread_id = ?
6759
- AND "createdAt" > ?
6768
+ AND "createdAt" > ?${resourceCondition}
6760
6769
  ORDER BY "createdAt" ASC, id ASC
6761
6770
  LIMIT ?
6762
6771
  )`);
6763
- params.push(target.threadId, target.createdAt, withNextMessages);
6772
+ params.push(target.threadId, target.createdAt);
6773
+ if (resourceId) params.push(resourceId);
6774
+ params.push(withNextMessages);
6764
6775
  }
6765
6776
  }
6766
6777
  if (unionQueries.length === 0) return null;
@@ -6856,7 +6867,10 @@ var MemoryLibSQL = class MemoryLibSQL extends _mastra_core_storage.MemoryStorage
6856
6867
  hasMore: false
6857
6868
  };
6858
6869
  if (perPage === 0 && include && include.length > 0) {
6859
- const includeMessages = await this._getIncludedMessages({ include });
6870
+ const includeMessages = await this._getIncludedMessages({
6871
+ include,
6872
+ resourceId
6873
+ });
6860
6874
  if (!includeMessages || includeMessages.length === 0) return {
6861
6875
  messages: [],
6862
6876
  total: 0,
@@ -6897,7 +6911,10 @@ var MemoryLibSQL = class MemoryLibSQL extends _mastra_core_storage.MemoryStorage
6897
6911
  };
6898
6912
  const messageIds = new Set(messages.map((m) => m.id));
6899
6913
  if (include && include.length > 0) {
6900
- const includeMessages = await this._getIncludedMessages({ include });
6914
+ const includeMessages = await this._getIncludedMessages({
6915
+ include,
6916
+ resourceId
6917
+ });
6901
6918
  if (includeMessages) {
6902
6919
  for (const includeMsg of includeMessages) if (!messageIds.has(includeMsg.id)) {
6903
6920
  messages.push(includeMsg);
@@ -6976,7 +6993,10 @@ var MemoryLibSQL = class MemoryLibSQL extends _mastra_core_storage.MemoryStorage
6976
6993
  hasMore: false
6977
6994
  };
6978
6995
  if (perPage === 0 && include && include.length > 0) {
6979
- const includeMessages = await this._getIncludedMessages({ include });
6996
+ const includeMessages = await this._getIncludedMessages({
6997
+ include,
6998
+ resourceId
6999
+ });
6980
7000
  if (!includeMessages || includeMessages.length === 0) return {
6981
7001
  messages: [],
6982
7002
  total: 0,
@@ -7016,7 +7036,10 @@ var MemoryLibSQL = class MemoryLibSQL extends _mastra_core_storage.MemoryStorage
7016
7036
  };
7017
7037
  const messageIds = new Set(messages.map((m) => m.id));
7018
7038
  if (include && include.length > 0) {
7019
- const includeMessages = await this._getIncludedMessages({ include });
7039
+ const includeMessages = await this._getIncludedMessages({
7040
+ include,
7041
+ resourceId
7042
+ });
7020
7043
  if (includeMessages) {
7021
7044
  for (const includeMsg of includeMessages) if (!messageIds.has(includeMsg.id)) {
7022
7045
  messages.push(includeMsg);