@mastra/libsql 1.26.1 → 1.26.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.
@@ -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.26.1"
6
+ version: "1.26.2"
7
7
  ---
8
8
 
9
9
  ## When to use
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.26.1",
2
+ "version": "1.26.2",
3
3
  "package": "@mastra/libsql",
4
4
  "exports": {},
5
5
  "modules": {}
@@ -151,6 +151,37 @@ const response = await memoryAgent.generate("What's my favorite color?", {
151
151
 
152
152
  To list all threads for a resource, or retrieve a specific thread, [use the memory API directly](https://mastra.ai/docs/memory/message-history).
153
153
 
154
+ ### Identify memory with scopes
155
+
156
+ Instead of a `memory` object, you can pass `scopes`: the addresses a run acts as, written as `<type>:<value>`. Memory reads the resource from a `resource:` scope and the thread from a `thread:` scope. Other scopes, such as `org:acme`, are passed to tools and processors.
157
+
158
+ ```typescript
159
+ const response = await memoryAgent.generate('Remember my favorite color is blue.', {
160
+ scopes: ['org:acme', 'resource:user-123', 'thread:conversation-123'],
161
+ })
162
+ ```
163
+
164
+ Scopes can also come from the agent and from the request context. Mastra combines all three sources:
165
+
166
+ ```typescript
167
+ export const memoryAgent = new Agent({
168
+ id: 'memory-agent',
169
+ name: 'Memory Agent',
170
+ scopes: ({ requestContext }) => {
171
+ // Set by your auth middleware. Request bodies can fill unreserved keys.
172
+ const orgId = requestContext.get('org-id')
173
+ return orgId ? [`org:${orgId}`] : []
174
+ },
175
+ memory: new Memory(),
176
+ })
177
+ ```
178
+
179
+ The resolver's inputs must come from the server, not the client: a request body can set any request context key that isn't reserved. Trusted server middleware can also set scopes directly with the `MASTRA_SCOPES_KEY` request context key. Visit [Request Context](https://mastra.ai/docs/server/request-context) for details. Clients can't send scopes in a request body.
180
+
181
+ You can mix scopes with `memory.resource`, `memory.thread`, or the resource and thread request context keys, as long as they agree. If a `resource:` or `thread:` scope names a different value than another source, the call throws an error.
182
+
183
+ Tools, processors, and subagents receive the run's other scopes, but not its `resource:` and `thread:` scopes. Each nested agent call picks its own resource and thread.
184
+
154
185
  ## Observational Memory
155
186
 
156
187
  Long conversations can fill the context window with raw message history and reduce agent performance. [Observational Memory](https://mastra.ai/docs/memory/observational-memory) uses background agents to compress older messages into observations. This reduces the context used by message history while retaining information for later turns.
@@ -12,18 +12,21 @@ Retention covers **growth tables** only: tables that accumulate rows unbounded a
12
12
 
13
13
  Storage adapters use the shared core retention contract for `prune()`, or a database-native mechanism when that better matches the backend.
14
14
 
15
- | Adapter | Mechanism | Retention support |
16
- | -------------------- | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
17
- | libSQL | `prune()` | All supported growth domains |
18
- | PostgreSQL | `prune()` | All supported growth domains. vNext observability drops expired partitions or chunks |
19
- | MongoDB | `prune()` or native TTL | All supported growth domains. Native TTL indexes are also available |
20
- | DuckDB | `prune()` | Observability spans, metrics, logs, scores, and feedback |
21
- | MySQL | `prune()` | Observability spans |
22
- | Microsoft SQL Server | `prune()` | Observability spans |
23
- | Oracle Database | `prune()` | Observability spans and logs |
24
- | Amazon Aurora DSQL | `prune()` | Observability spans |
25
- | Google Cloud Spanner | `prune()` | Observability spans, plus metrics when metrics storage is enabled |
26
- | ClickHouse | Native TTL | Observability spans, metrics, logs, scores, and feedback. When all five signals have finite retention, deletion-request records expire after the longest signal retention plus 30 days |
15
+ | Adapter | Mechanism | Retention support |
16
+ | --------------------------------- | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
17
+ | libSQL | `prune()` | All supported growth domains |
18
+ | PostgreSQL | `prune()` | All supported growth domains. vNext observability drops expired partitions or chunks |
19
+ | MongoDB | `prune()` or native TTL | All supported growth domains. Native TTL indexes are also available |
20
+ | DuckDB | `prune()` | Observability spans, metrics, logs, scores, and feedback |
21
+ | MySQL | `prune()` | Observability spans, durable agent run fencing (`runOwnership`, `runFences`) |
22
+ | Microsoft SQL Server | `prune()` | Observability spans, durable agent run fencing (`runOwnership`, `runFences`) |
23
+ | Oracle Database | `prune()` | Observability spans and logs, durable agent run fencing (`runOwnership`, `runFences`) |
24
+ | Amazon Aurora DSQL | `prune()` | Observability spans, durable agent run fencing (`runOwnership`, `runFences`) |
25
+ | Google Cloud Spanner | `prune()` | Observability spans, plus metrics when metrics storage is enabled. Durable agent run fencing (`runOwnership`, `runFences`) |
26
+ | DynamoDB | `prune()` | Durable agent run fencing (`runOwnership`, `runFences`) |
27
+ | Convex | `prune()` | Durable agent run fencing (`runOwnership`, `runFences`). Redeploy your Convex functions after upgrading |
28
+ | Cloudflare D1 and Durable Objects | `prune()` | Durable agent run fencing (`runOwnership`, `runFences`) |
29
+ | ClickHouse | Native TTL | Observability spans, metrics, logs, scores, and feedback. When all five signals have finite retention, deletion-request records expire after the longest signal retention plus 30 days |
27
30
 
28
31
  ## Storage-specific maintenance
29
32
 
package/dist/index.cjs CHANGED
@@ -11823,8 +11823,10 @@ var NotificationsLibSQL = class NotificationsLibSQL extends _mastra_core_storage
11823
11823
  async init() {
11824
11824
  await this.#db.createTable({
11825
11825
  tableName: _mastra_core_storage.TABLE_NOTIFICATIONS,
11826
- schema: _mastra_core_storage.TABLE_SCHEMAS[_mastra_core_storage.TABLE_NOTIFICATIONS]
11826
+ schema: _mastra_core_storage.TABLE_SCHEMAS[_mastra_core_storage.TABLE_NOTIFICATIONS],
11827
+ compositePrimaryKey: _mastra_core_storage.TABLE_CONFIGS[_mastra_core_storage.TABLE_NOTIFICATIONS]?.compositePrimaryKey
11827
11828
  });
11829
+ await this.ensureUniqueKey();
11828
11830
  await this.#client.batch([
11829
11831
  {
11830
11832
  sql: `CREATE INDEX IF NOT EXISTS idx_notifications_thread_status_updated ON "${_mastra_core_storage.TABLE_NOTIFICATIONS}" ("threadId", "status", "updatedAt")`,
@@ -11840,6 +11842,21 @@ var NotificationsLibSQL = class NotificationsLibSQL extends _mastra_core_storage
11840
11842
  }
11841
11843
  ], "write");
11842
11844
  }
11845
+ /**
11846
+ * Tables created before the composite primary key was declared have no key.
11847
+ * SQLite cannot add a primary key in place, so enforce the same uniqueness with
11848
+ * a unique index. Tables that already have the key are skipped, since SQLite
11849
+ * would otherwise maintain a redundant second index. If duplicate rows exist
11850
+ * the index cannot be built; warn instead of blocking init.
11851
+ */
11852
+ async ensureUniqueKey() {
11853
+ if ((await this.#client.execute(`PRAGMA table_info("${_mastra_core_storage.TABLE_NOTIFICATIONS}")`)).rows.some((row) => Number(row.pk) > 0)) return;
11854
+ try {
11855
+ await this.#client.execute(`CREATE UNIQUE INDEX IF NOT EXISTS idx_notifications_thread_id_unique ON "${_mastra_core_storage.TABLE_NOTIFICATIONS}" ("threadId", "id")`);
11856
+ } catch (error) {
11857
+ this.logger?.warn?.(`Could not enforce unique ("threadId", "id") on ${_mastra_core_storage.TABLE_NOTIFICATIONS}; remove duplicate rows and restart to add it.`, error);
11858
+ }
11859
+ }
11843
11860
  async dangerouslyClearAll() {
11844
11861
  await this.#db.deleteData({ tableName: _mastra_core_storage.TABLE_NOTIFICATIONS });
11845
11862
  }