@mastra/libsql 1.20.0-alpha.0 → 1.20.0-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 CHANGED
@@ -1,5 +1,41 @@
1
1
  # @mastra/libsql
2
2
 
3
+ ## 1.20.0-alpha.2
4
+
5
+ ### Patch Changes
6
+
7
+ - Fixed generated thread titles being clobbered during a turn ([#21041](https://github.com/mastra-ai/mastra/pull/21041))
8
+
9
+ `updateThread` required both `title` and `metadata`, so callers that only needed to
10
+ change metadata (message persistence, working memory, observational memory, channel
11
+ subscriptions) had to read the thread and pass its title back. When title generation
12
+ finished between that read and the write, the freshly generated title was overwritten
13
+ with the stale one.
14
+
15
+ `title` and `metadata` are now independently optional: omitting one leaves that column
16
+ untouched. Callers that only change metadata no longer send a title, and message
17
+ persistence no longer rewrites a thread row it just read.
18
+
19
+ - Updated dependencies [[`1c75e32`](https://github.com/mastra-ai/mastra/commit/1c75e32f7fc0b9fb6f548b4407feaec8a1440212), [`c47165c`](https://github.com/mastra-ai/mastra/commit/c47165c983c87594c6952f1fd2fa51a90205034c), [`e08e789`](https://github.com/mastra-ai/mastra/commit/e08e789c1bf4cd2fe46363f7a4728536ceccc9bd), [`35cc901`](https://github.com/mastra-ai/mastra/commit/35cc90102cf834a84827acaf9eee0b6d6d1e2a3b), [`a8b4cf0`](https://github.com/mastra-ai/mastra/commit/a8b4cf02823cffebc4751a53337dfacf097c1ae1), [`f33264f`](https://github.com/mastra-ai/mastra/commit/f33264f517ae603279afd5c4251e2b40f6dd3618), [`689f2c4`](https://github.com/mastra-ai/mastra/commit/689f2c4b6c0835fe455702b01d21daa8abcd9331), [`eeae63e`](https://github.com/mastra-ai/mastra/commit/eeae63e7fbe8e1f237adc69bca6e2ac13c5ca907), [`4c186a0`](https://github.com/mastra-ai/mastra/commit/4c186a017275f45e6ed4c09de0f89550e2d09e8c), [`b0fa077`](https://github.com/mastra-ai/mastra/commit/b0fa077bcbc9b08551846fe372a0d3d15b71ed72)]:
20
+ - @mastra/core@1.58.0-alpha.8
21
+
22
+ ## 1.20.0-alpha.1
23
+
24
+ ### Patch Changes
25
+
26
+ - 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))
27
+
28
+ **Behaviour change in the in-memory store**
29
+
30
+ 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.
31
+
32
+ The in-memory store also ignored `include` in `listMessagesByResourceId`. It now returns the included messages, like `@mastra/libsql` and `@mastra/pg` do.
33
+
34
+ Fixes #20604.
35
+
36
+ - 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)]:
37
+ - @mastra/core@1.58.0-alpha.5
38
+
3
39
  ## 1.20.0-alpha.0
4
40
 
5
41
  ### 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.2"
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.2",
3
3
  "package": "@mastra/libsql",
4
4
  "exports": {},
5
5
  "modules": {}
@@ -156,7 +156,7 @@ const memory = new Memory({
156
156
  })
157
157
  ```
158
158
 
159
- OM requires a storage adapter that supports it: `@mastra/libsql`, `@mastra/pg`, or `@mastra/mongodb`.
159
+ OM requires a storage adapter that supports it: `@mastra/libsql`, `@mastra/pg`, `@mastra/mongodb`, or `@mastra/oracledb`.
160
160
 
161
161
  > **Note:** If you switch the Observer to a weaker model and see facts collapse to a generic `User`, use [`observation.instruction`](https://mastra.ai/reference/memory/observational-memory) to teach the Observer how to read the `<turn>` tag.
162
162
 
@@ -148,6 +148,7 @@ Each vector store page below includes installation instructions, configuration p
148
148
  - [libSQL](https://mastra.ai/reference/vectors/libsql)
149
149
  - [MongoDB](https://mastra.ai/reference/vectors/mongodb)
150
150
  - [OpenSearch](https://mastra.ai/reference/vectors/opensearch)
151
+ - [OracleDB](https://mastra.ai/reference/vectors/oracledb)
151
152
  - [Pinecone](https://mastra.ai/reference/vectors/pinecone)
152
153
  - [PostgreSQL](https://mastra.ai/reference/vectors/pg)
153
154
  - [Qdrant](https://mastra.ai/reference/vectors/qdrant)
@@ -180,7 +181,7 @@ const agent = new Agent({
180
181
  })
181
182
  ```
182
183
 
183
- > **Note:** `scope: 'resource'` is supported by the LibSQL, PostgreSQL, MongoDB, and Upstash storage adapters.
184
+ > **Note:** `scope: 'resource'` is supported by the LibSQL, OracleDB, PostgreSQL, MongoDB, and Upstash storage adapters.
184
185
 
185
186
  ### Metadata filtering
186
187
 
@@ -129,6 +129,7 @@ Resource-scoped working memory requires specific storage adapters that support t
129
129
 
130
130
  - **libSQL** (`@mastra/libsql`)
131
131
  - **PostgreSQL** (`@mastra/pg`)
132
+ - **OracleDB** (`@mastra/oracledb`)
132
133
  - **Upstash** (`@mastra/upstash`)
133
134
  - **MongoDB** (`@mastra/mongodb`)
134
135
 
@@ -193,6 +193,7 @@ Each provider page includes installation instructions, configuration parameters,
193
193
  - [libSQL](https://mastra.ai/reference/storage/libsql)
194
194
  - [PostgreSQL](https://mastra.ai/reference/storage/postgresql)
195
195
  - [MongoDB](https://mastra.ai/reference/storage/mongodb)
196
+ - [OracleDB](https://mastra.ai/reference/storage/oracledb)
196
197
  - [Upstash](https://mastra.ai/reference/storage/upstash)
197
198
  - [Redis](https://mastra.ai/reference/storage/redis)
198
199
  - [Cloudflare D1](https://mastra.ai/reference/storage/cloudflare-d1)
@@ -81,13 +81,14 @@ Each snapshot includes the `runId`, input, step status (`success`, `suspended`,
81
81
 
82
82
  ## How snapshots are saved and retrieved
83
83
 
84
- Snapshots are saved to the configured storage system. By default, they use libSQL, but you can configure Upstash or PostgreSQL instead. Each snapshot is saved in the `workflow_snapshots` table and identified by the workflow's `runId`.
84
+ Snapshots are saved to the configured storage system. By default, they use libSQL, but you can configure Upstash, PostgreSQL, or OracleDB instead. Each snapshot is saved in the `workflow_snapshots` table and identified by the workflow's `runId`.
85
85
 
86
86
  Read more about:
87
87
 
88
88
  - [libSQL Storage](https://mastra.ai/reference/storage/libsql)
89
89
  - [Upstash Storage](https://mastra.ai/reference/storage/upstash)
90
90
  - [PostgreSQL Storage](https://mastra.ai/reference/storage/postgresql)
91
+ - [OracleDB Storage](https://mastra.ai/reference/storage/oracledb)
91
92
 
92
93
  ### Saving snapshots
93
94
 
@@ -141,6 +142,7 @@ export const mastra = new Mastra({
141
142
 
142
143
  - [libSQL Storage](https://mastra.ai/reference/storage/libsql)
143
144
  - [PostgreSQL Storage](https://mastra.ai/reference/storage/postgresql)
145
+ - [OracleDB Storage](https://mastra.ai/reference/storage/oracledb)
144
146
  - [MongoDB Storage](https://mastra.ai/reference/storage/mongodb)
145
147
  - [Upstash Storage](https://mastra.ai/reference/storage/upstash)
146
148
  - [Cloudflare D1](https://mastra.ai/reference/storage/cloudflare-d1)
@@ -436,6 +436,23 @@ export const ragAgent = new Agent({
436
436
  })
437
437
  ```
438
438
 
439
+ **OracleDB**:
440
+
441
+ ```ts
442
+ import { ORACLEDB_PROMPT } from '@mastra/oracledb'
443
+
444
+ export const ragAgent = new Agent({
445
+ id: 'rag-agent',
446
+ name: 'RAG Agent',
447
+ model: 'openai/gpt-5.6-sol',
448
+ instructions: `
449
+ Process queries using the provided context. Structure responses to be concise and relevant.
450
+ ${ORACLEDB_PROMPT}
451
+ `,
452
+ tools: { vectorQueryTool },
453
+ })
454
+ ```
455
+
439
456
  **S3Vectors**:
440
457
 
441
458
  ```ts
@@ -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);
@@ -7427,7 +7450,7 @@ var MemoryLibSQL = class MemoryLibSQL extends _mastra_core_storage.MemoryStorage
7427
7450
  const now = /* @__PURE__ */ new Date();
7428
7451
  const updatedThread = {
7429
7452
  ...thread,
7430
- title,
7453
+ title: title ?? thread.title,
7431
7454
  metadata: {
7432
7455
  ...thread.metadata,
7433
7456
  ...metadata
@@ -7436,9 +7459,9 @@ var MemoryLibSQL = class MemoryLibSQL extends _mastra_core_storage.MemoryStorage
7436
7459
  };
7437
7460
  try {
7438
7461
  await this.#client.execute({
7439
- sql: `UPDATE ${_mastra_core_storage.TABLE_THREADS} SET title = ?, metadata = jsonb(?), updatedAt = ? WHERE id = ?`,
7462
+ sql: `UPDATE ${_mastra_core_storage.TABLE_THREADS} SET title = COALESCE(?, title), metadata = jsonb(?), updatedAt = ? WHERE id = ?`,
7440
7463
  args: [
7441
- title,
7464
+ title ?? null,
7442
7465
  JSON.stringify(updatedThread.metadata),
7443
7466
  now.toISOString(),
7444
7467
  id