@mastra/pg 1.8.4 → 1.8.5-alpha.0

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,14 @@
1
1
  # @mastra/pg
2
2
 
3
+ ## 1.8.5-alpha.0
4
+
5
+ ### Patch Changes
6
+
7
+ - Fixed thread and message timestamp handling to use timezone-aware columns (TIMESTAMPTZ) for sorting and date range filtering. Previously, ORDER BY and date range queries used TIMESTAMP columns which could produce incorrect ordering when the PostgreSQL server timezone differs from UTC. Also fixed timestamp values passed to UPDATE queries to use Date objects instead of ISO strings, preventing timezone information from being stripped when stored in TIMESTAMP columns. ([#14297](https://github.com/mastra-ai/mastra/pull/14297))
8
+
9
+ - Updated dependencies [[`9140989`](https://github.com/mastra-ai/mastra/commit/91409890e83f4f1d9c1b39223f1af91a6a53b549), [`d7c98cf`](https://github.com/mastra-ai/mastra/commit/d7c98cfc9d75baba9ecbf1a8835b5183d0a0aec8), [`acf5fbc`](https://github.com/mastra-ai/mastra/commit/acf5fbcb890dc7ca7167bec386ce5874dfadb997), [`24ca2ae`](https://github.com/mastra-ai/mastra/commit/24ca2ae57538ec189fabb9daee6175ad27035853), [`0762516`](https://github.com/mastra-ai/mastra/commit/07625167e029a8268ea7aaf0402416e6d8832874), [`2de3d36`](https://github.com/mastra-ai/mastra/commit/2de3d36932b7f73ad26bc403f7da26cfe89e903e), [`d3736cb`](https://github.com/mastra-ai/mastra/commit/d3736cb9ce074d2b8e8b00218a01f790fe81a1b4), [`c627366`](https://github.com/mastra-ai/mastra/commit/c6273666f9ef4c8c617c68b7d07fe878a322f85c)]:
10
+ - @mastra/core@1.18.1-alpha.1
11
+
3
12
  ## 1.8.4
4
13
 
5
14
  ### Patch Changes
@@ -3,7 +3,7 @@ name: mastra-pg
3
3
  description: Documentation for @mastra/pg. Use when working with @mastra/pg APIs, configuration, or implementation.
4
4
  metadata:
5
5
  package: "@mastra/pg"
6
- version: "1.8.4"
6
+ version: "1.8.5-alpha.0"
7
7
  ---
8
8
 
9
9
  ## When to use
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.8.4",
2
+ "version": "1.8.5-alpha.0",
3
3
  "package": "@mastra/pg",
4
4
  "exports": {},
5
5
  "modules": {}
@@ -18,18 +18,33 @@ After getting a response from the LLM, all new messages (user, assistant, and to
18
18
 
19
19
  ## Quickstart
20
20
 
21
- Semantic recall is enabled by default, so if you give your agent memory it will be included:
21
+ Semantic recall is disabled by default. To enable it, set `semanticRecall: true` in `options` and provide a `vector` store and `embedder`:
22
22
 
23
23
  ```typescript
24
24
  import { Agent } from '@mastra/core/agent'
25
25
  import { Memory } from '@mastra/memory'
26
+ import { LibSQLStore, LibSQLVector } from '@mastra/libsql'
27
+ import { ModelRouterEmbeddingModel } from '@mastra/core/llm'
26
28
 
27
29
  const agent = new Agent({
28
30
  id: 'support-agent',
29
31
  name: 'SupportAgent',
30
32
  instructions: 'You are a helpful support agent.',
31
33
  model: 'openai/gpt-5.4',
32
- memory: new Memory(),
34
+ memory: new Memory({
35
+ storage: new LibSQLStore({
36
+ id: 'agent-storage',
37
+ url: 'file:./local.db',
38
+ }),
39
+ vector: new LibSQLVector({
40
+ id: 'agent-vector',
41
+ url: 'file:./local.db',
42
+ }),
43
+ embedder: new ModelRouterEmbeddingModel('openai/text-embedding-3-small'),
44
+ options: {
45
+ semanticRecall: true,
46
+ },
47
+ }),
33
48
  })
34
49
  ```
35
50
 
@@ -77,6 +92,9 @@ const agent = new Agent({
77
92
  id: 'agent-vector',
78
93
  url: 'file:./local.db',
79
94
  }),
95
+ options: {
96
+ semanticRecall: true,
97
+ },
80
98
  }),
81
99
  })
82
100
  ```
@@ -139,6 +157,9 @@ import { ModelRouterEmbeddingModel } from '@mastra/core/llm'
139
157
  const agent = new Agent({
140
158
  memory: new Memory({
141
159
  embedder: new ModelRouterEmbeddingModel('openai/text-embedding-3-small'),
160
+ options: {
161
+ semanticRecall: true,
162
+ },
142
163
  }),
143
164
  })
144
165
  ```
@@ -262,26 +283,14 @@ const agent = new Agent({
262
283
 
263
284
  For detailed information about index configuration options and performance tuning, see the [PgVector configuration guide](https://mastra.ai/reference/vectors/pg).
264
285
 
265
- ## Disabling
286
+ ## Disable semantic recall
266
287
 
267
- Semantic recall has a performance impact. New messages are converted into embeddings and used to query a vector database before new messages are sent to the LLM.
268
-
269
- Semantic recall is enabled by default but can be disabled when not needed:
270
-
271
- ```typescript
272
- const agent = new Agent({
273
- memory: new Memory({
274
- options: {
275
- semanticRecall: false,
276
- },
277
- }),
278
- })
279
- ```
288
+ Semantic recall is disabled by default (`semanticRecall: false`). Each call adds latency because new messages are converted into embeddings and used to query a vector database before the LLM receives them.
280
289
 
281
- You might want to disable semantic recall in scenarios like:
290
+ Keep semantic recall disabled when:
282
291
 
283
- - When message history provides sufficient context for the current conversation.
284
- - In performance-sensitive applications, like realtime two-way audio, where the added latency of creating embeddings and running vector queries is noticeable.
292
+ - Message history provides sufficient context for the current conversation.
293
+ - You're building performance-sensitive applications, like realtime two-way audio, where embedding and vector query latency is noticeable.
285
294
 
286
295
  ## Viewing recalled messages
287
296
 
@@ -14,7 +14,7 @@ export const mastra = new Mastra({
14
14
  })
15
15
  ```
16
16
 
17
- > **Sharing the database with Mastra Studio:** When running `mastra dev` alongside your application (e.g., Next.js), use an absolute path to ensure both processes access the same database:
17
+ > **Sharing the database with Studio:** When running `mastra dev` alongside your application (e.g., Next.js), use an absolute path to ensure both processes access the same database:
18
18
  >
19
19
  > ```typescript
20
20
  > url: 'file:/absolute/path/to/your/project/mastra.db'
@@ -129,7 +129,7 @@ Mastra organizes conversations using two identifiers:
129
129
 
130
130
  Both identifiers are required for agents to store information:
131
131
 
132
- **Generate**:
132
+ **.generate()**:
133
133
 
134
134
  ```typescript
135
135
  const response = await agent.generate('hello', {
@@ -140,7 +140,7 @@ const response = await agent.generate('hello', {
140
140
  })
141
141
  ```
142
142
 
143
- **Stream**:
143
+ **.stream()**:
144
144
 
145
145
  ```typescript
146
146
  const stream = await agent.stream('hello', {
@@ -151,7 +151,7 @@ const stream = await agent.stream('hello', {
151
151
  })
152
152
  ```
153
153
 
154
- > **Note:** [Studio](https://mastra.ai/docs/getting-started/studio) automatically generates a thread and resource ID for you. When calling `stream()` or `generate()` yourself, remember to provide these identifiers explicitly.
154
+ > **Note:** [Studio](https://mastra.ai/docs/studio/overview) automatically generates a thread and resource ID for you. When calling `stream()` or `generate()` yourself, remember to provide these identifiers explicitly.
155
155
 
156
156
  ### Thread title generation
157
157
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  The DynamoDB storage implementation provides a scalable and performant NoSQL database solution for Mastra, leveraging a single-table design pattern with [ElectroDB](https://electrodb.dev/).
4
4
 
5
- > **Observability Not Supported:** DynamoDB storage **doesn't support the observability domain**. Traces from the `DefaultExporter` can't be persisted to DynamoDB, and Mastra Studio's observability features won't work with DynamoDB as your only storage provider. To enable observability, use [composite storage](https://mastra.ai/reference/storage/composite) to route observability data to a supported provider like ClickHouse or PostgreSQL.
5
+ > **Observability Not Supported:** DynamoDB storage **doesn't support the observability domain**. Traces from the `DefaultExporter` can't be persisted to DynamoDB, and [Studio's](https://mastra.ai/docs/studio/overview) observability features won't work with DynamoDB as your only storage provider. To enable observability, use [composite storage](https://mastra.ai/reference/storage/composite) to route observability data to a supported provider like ClickHouse or PostgreSQL.
6
6
 
7
7
  > **Item Size Limit:** DynamoDB enforces a **400 KB maximum item size**. This limit can be exceeded when storing messages with base64-encoded attachments such as images. See [Handling large attachments](https://mastra.ai/docs/memory/storage) for workarounds including uploading attachments to external storage.
8
8
 
package/dist/index.cjs CHANGED
@@ -7355,7 +7355,7 @@ var MemoryPG = class _MemoryPG extends storage.MemoryStorage {
7355
7355
  };
7356
7356
  }
7357
7357
  const limitValue = perPageInput === false ? total : perPage;
7358
- const dataQuery = `SELECT id, "resourceId", title, metadata, "createdAt", "createdAtZ", "updatedAt", "updatedAtZ" ${baseQuery} ORDER BY "${field}" ${direction} LIMIT $${paramIndex} OFFSET $${paramIndex + 1}`;
7358
+ const dataQuery = `SELECT id, "resourceId", title, metadata, "createdAt", "createdAtZ", "updatedAt", "updatedAtZ" ${baseQuery} ORDER BY COALESCE("${field}Z", "${field}") ${direction} LIMIT $${paramIndex} OFFSET $${paramIndex + 1}`;
7359
7359
  const rows = await this.#db.client.manyOrNone(
7360
7360
  dataQuery,
7361
7361
  [...queryParams, limitValue, offset]
@@ -7473,7 +7473,7 @@ var MemoryPG = class _MemoryPG extends storage.MemoryStorage {
7473
7473
  ...metadata
7474
7474
  };
7475
7475
  try {
7476
- const now = (/* @__PURE__ */ new Date()).toISOString();
7476
+ const now = /* @__PURE__ */ new Date();
7477
7477
  const thread = await this.#db.client.one(
7478
7478
  `UPDATE ${threadTableName}
7479
7479
  SET
@@ -7719,7 +7719,7 @@ var MemoryPG = class _MemoryPG extends storage.MemoryStorage {
7719
7719
  const { offset, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
7720
7720
  try {
7721
7721
  const { field, direction } = this.parseOrderBy(orderBy, "ASC");
7722
- const orderByStatement = `ORDER BY "${field}" ${direction}`;
7722
+ const orderByStatement = `ORDER BY COALESCE("${field}Z", "${field}") ${direction}`;
7723
7723
  const selectStatement = `SELECT id, content, role, type, "createdAt", "createdAtZ", thread_id AS "threadId", "resourceId"`;
7724
7724
  const tableName = getTableName3({ indexName: storage.TABLE_MESSAGES, schemaName: getSchemaName3(this.#schema) });
7725
7725
  const conditions = [`thread_id IN (${inPlaceholders(threadIds.length)})`];
@@ -7858,7 +7858,7 @@ var MemoryPG = class _MemoryPG extends storage.MemoryStorage {
7858
7858
  const { offset, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
7859
7859
  try {
7860
7860
  const { field, direction } = this.parseOrderBy(orderBy, "ASC");
7861
- const orderByStatement = `ORDER BY "${field}" ${direction}`;
7861
+ const orderByStatement = `ORDER BY COALESCE("${field}Z", "${field}") ${direction}`;
7862
7862
  const selectStatement = `SELECT id, content, role, type, "createdAt", "createdAtZ", thread_id AS "threadId", "resourceId"`;
7863
7863
  const tableName = getTableName3({ indexName: storage.TABLE_MESSAGES, schemaName: getSchemaName3(this.#schema) });
7864
7864
  const conditions = [];
@@ -7868,12 +7868,12 @@ var MemoryPG = class _MemoryPG extends storage.MemoryStorage {
7868
7868
  queryParams.push(resourceId);
7869
7869
  if (filter?.dateRange?.start) {
7870
7870
  const startOp = filter.dateRange.startExclusive ? ">" : ">=";
7871
- conditions.push(`"createdAt" ${startOp} $${paramIndex++}`);
7871
+ conditions.push(`COALESCE("createdAtZ", "createdAt") ${startOp} $${paramIndex++}`);
7872
7872
  queryParams.push(filter.dateRange.start);
7873
7873
  }
7874
7874
  if (filter?.dateRange?.end) {
7875
7875
  const endOp = filter.dateRange.endExclusive ? "<" : "<=";
7876
- conditions.push(`"createdAt" ${endOp} $${paramIndex++}`);
7876
+ conditions.push(`COALESCE("createdAtZ", "createdAt") ${endOp} $${paramIndex++}`);
7877
7877
  queryParams.push(filter.dateRange.end);
7878
7878
  }
7879
7879
  const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
@@ -8013,8 +8013,8 @@ var MemoryPG = class _MemoryPG extends storage.MemoryStorage {
8013
8013
  message.id,
8014
8014
  message.threadId,
8015
8015
  typeof message.content === "string" ? message.content : JSON.stringify(message.content),
8016
- message.createdAt || (/* @__PURE__ */ new Date()).toISOString(),
8017
- message.createdAt || (/* @__PURE__ */ new Date()).toISOString(),
8016
+ message.createdAt || /* @__PURE__ */ new Date(),
8017
+ message.createdAt || /* @__PURE__ */ new Date(),
8018
8018
  message.role,
8019
8019
  message.type || "v2",
8020
8020
  message.resourceId
@@ -8022,14 +8022,14 @@ var MemoryPG = class _MemoryPG extends storage.MemoryStorage {
8022
8022
  );
8023
8023
  }
8024
8024
  const threadTableName = getTableName3({ indexName: storage.TABLE_THREADS, schemaName: getSchemaName3(this.#schema) });
8025
- const nowStr = (/* @__PURE__ */ new Date()).toISOString();
8025
+ const now = /* @__PURE__ */ new Date();
8026
8026
  await t.none(
8027
8027
  `UPDATE ${threadTableName}
8028
8028
  SET
8029
8029
  "updatedAt" = $1,
8030
8030
  "updatedAtZ" = $2
8031
8031
  WHERE id = $3`,
8032
- [nowStr, nowStr, threadId]
8032
+ [now, now, threadId]
8033
8033
  );
8034
8034
  });
8035
8035
  const messagesWithParsedContent = messages.map((message) => {