@mastra/pg 0.11.1-alpha.1 → 0.12.0-alpha.3

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.
@@ -1,23 +1,23 @@
1
1
 
2
- > @mastra/pg@0.11.1-alpha.1 build /home/runner/work/mastra/mastra/stores/pg
2
+ > @mastra/pg@0.12.0-alpha.3 build /home/runner/work/mastra/mastra/stores/pg
3
3
  > tsup src/index.ts --format esm,cjs --experimental-dts --clean --treeshake=smallest --splitting
4
4
 
5
5
  CLI Building entry: src/index.ts
6
6
  CLI Using tsconfig: tsconfig.json
7
7
  CLI tsup v8.5.0
8
8
  TSC Build start
9
- TSC ⚡️ Build success in 10897ms
9
+ TSC ⚡️ Build success in 11837ms
10
10
  DTS Build start
11
11
  CLI Target: es2022
12
12
  Analysis will use the bundled TypeScript version 5.8.3
13
13
  Writing package typings: /home/runner/work/mastra/mastra/stores/pg/dist/_tsup-dts-rollup.d.ts
14
14
  Analysis will use the bundled TypeScript version 5.8.3
15
15
  Writing package typings: /home/runner/work/mastra/mastra/stores/pg/dist/_tsup-dts-rollup.d.cts
16
- DTS ⚡️ Build success in 11697ms
16
+ DTS ⚡️ Build success in 12951ms
17
17
  CLI Cleaning output folder
18
18
  ESM Build start
19
19
  CJS Build start
20
- ESM dist/index.js 83.06 KB
21
- ESM ⚡️ Build success in 1628ms
22
- CJS dist/index.cjs 84.43 KB
23
- CJS ⚡️ Build success in 1628ms
20
+ ESM dist/index.js 86.23 KB
21
+ ESM ⚡️ Build success in 1680ms
22
+ CJS dist/index.cjs 87.61 KB
23
+ CJS ⚡️ Build success in 1680ms
package/CHANGELOG.md CHANGED
@@ -1,5 +1,32 @@
1
1
  # @mastra/pg
2
2
 
3
+ ## 0.12.0-alpha.3
4
+
5
+ ### Minor Changes
6
+
7
+ - 8a3bfd2: Update peerdeps to latest core
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [792c4c0]
12
+ - Updated dependencies [502fe05]
13
+ - Updated dependencies [4efcfa0]
14
+ - @mastra/core@0.10.7-alpha.3
15
+
16
+ ## 0.11.1-alpha.2
17
+
18
+ ### Patch Changes
19
+
20
+ - 15e9d26: Added per-resource working memory for LibSQL, Upstash, and PG
21
+ - 0fb9d64: [MASTRA-4018] Update saveMessages in storage adapters to upsert messages
22
+ - 144eb0b: [MASTRA-3669] Metadata Filter Types
23
+ - f0150c4: Fix LibSQLStore and PgStore getMessagesPaginated implementation
24
+ - Updated dependencies [15e9d26]
25
+ - Updated dependencies [07d6d88]
26
+ - Updated dependencies [5d74aab]
27
+ - Updated dependencies [144eb0b]
28
+ - @mastra/core@0.10.7-alpha.2
29
+
3
30
  ## 0.11.1-alpha.1
4
31
 
5
32
  ### Patch Changes
@@ -1,4 +1,5 @@
1
1
  import { BaseFilterTranslator } from '@mastra/core/vector/filter';
2
+ import type { BlacklistedRootOperators } from '@mastra/core/vector/filter';
2
3
  import type { CreateIndexParams } from '@mastra/core/vector';
3
4
  import type { DeleteIndexParams } from '@mastra/core/vector';
4
5
  import type { DeleteVectorParams } from '@mastra/core/vector';
@@ -6,12 +7,14 @@ import type { DescribeIndexParams } from '@mastra/core/vector';
6
7
  import type { EvalRow } from '@mastra/core/storage';
7
8
  import type { IndexStats } from '@mastra/core/vector';
8
9
  import type { ISSLConfig } from 'pg-promise/typescript/pg-subset';
10
+ import type { LogicalOperatorValueMap } from '@mastra/core/vector/filter';
9
11
  import type { MastraMessageContentV2 } from '@mastra/core/agent';
10
12
  import type { MastraMessageV1 } from '@mastra/core/memory';
11
13
  import type { MastraMessageV2 } from '@mastra/core/agent';
12
14
  import { MastraStorage } from '@mastra/core/storage';
13
15
  import { MastraVector } from '@mastra/core/vector';
14
16
  import type { OperatorSupport } from '@mastra/core/vector/filter';
17
+ import type { OperatorValueMap } from '@mastra/core/vector/filter';
15
18
  import type { PaginationArgs } from '@mastra/core/storage';
16
19
  import type { PaginationInfo } from '@mastra/core/storage';
17
20
  import pg from 'pg';
@@ -19,10 +22,12 @@ import type { QueryResult } from '@mastra/core/vector';
19
22
  import type { QueryVectorParams } from '@mastra/core/vector';
20
23
  import type { StorageColumn } from '@mastra/core/storage';
21
24
  import type { StorageGetMessagesArg } from '@mastra/core/storage';
25
+ import type { StorageResourceType } from '@mastra/core/storage';
22
26
  import type { StorageThreadType } from '@mastra/core/memory';
23
27
  import type { TABLE_NAMES } from '@mastra/core/storage';
24
28
  import type { UpdateVectorParams } from '@mastra/core/vector';
25
29
  import type { UpsertVectorParams } from '@mastra/core/vector';
30
+ import type { VectorFieldValue } from '@mastra/core/vector/filter';
26
31
  import type { VectorFilter } from '@mastra/core/vector/filter';
27
32
  import type { WorkflowRun } from '@mastra/core/storage';
28
33
  import type { WorkflowRuns } from '@mastra/core/storage';
@@ -61,7 +66,7 @@ export declare const baseTestConfigs: {
61
66
  }[];
62
67
  };
63
68
 
64
- export declare function buildFilterQuery(filter: VectorFilter, minScore: number, topK: number): FilterResult;
69
+ export declare function buildFilterQuery(filter: PGVectorFilter, minScore: number, topK: number): FilterResult;
65
70
 
66
71
  export declare const calculateRecall: (actual: number[], expected: number[], k: number) => number;
67
72
 
@@ -126,6 +131,8 @@ declare interface IVFConfig {
126
131
 
127
132
  export declare function measureLatency<T>(fn: () => Promise<T>): Promise<[number, T]>;
128
133
 
134
+ declare type PGBlacklisted = BlacklistedRootOperators | '$contains' | '$size';
135
+
129
136
  declare interface PgCreateIndexParams extends CreateIndexParams {
130
137
  indexConfig?: IndexConfig;
131
138
  buildIndex?: boolean;
@@ -147,13 +154,15 @@ declare interface PgDefineIndexParams {
147
154
  * - Can take either a single condition or an array of conditions
148
155
  *
149
156
  */
150
- export declare class PGFilterTranslator extends BaseFilterTranslator {
157
+ export declare class PGFilterTranslator extends BaseFilterTranslator<PGVectorFilter> {
151
158
  protected getSupportedOperators(): OperatorSupport;
152
- translate(filter?: VectorFilter): VectorFilter;
159
+ translate(filter?: PGVectorFilter): PGVectorFilter;
153
160
  private translateNode;
154
161
  private translateRegexPattern;
155
162
  }
156
163
 
164
+ declare type PGFilterValue = VectorFieldValue | RegExp;
165
+
157
166
  declare interface PGIndexStats extends IndexStats {
158
167
  type: IndexType;
159
168
  config: {
@@ -166,7 +175,17 @@ declare interface PGIndexStats extends IndexStats {
166
175
  export { PGIndexStats }
167
176
  export { PGIndexStats as PGIndexStats_alias_1 }
168
177
 
169
- declare interface PgQueryVectorParams extends QueryVectorParams {
178
+ declare type PGOperatorValueMap = Omit<OperatorValueMap, '$in' | '$all' | '$nin' | '$eq' | '$ne'> & {
179
+ $size: number;
180
+ $contains: VectorFieldValue | Record<string, unknown>;
181
+ $all: VectorFieldValue;
182
+ $in: VectorFieldValue;
183
+ $nin: VectorFieldValue;
184
+ $eq: VectorFieldValue;
185
+ $ne: VectorFieldValue;
186
+ };
187
+
188
+ declare interface PgQueryVectorParams extends QueryVectorParams<PGVectorFilter> {
170
189
  minScore?: number;
171
190
  /**
172
191
  * HNSW search parameter. Controls the size of the dynamic candidate
@@ -180,7 +199,7 @@ declare interface PgQueryVectorParams extends QueryVectorParams {
180
199
  probes?: number;
181
200
  }
182
201
 
183
- declare class PgVector extends MastraVector {
202
+ declare class PgVector extends MastraVector<PGVectorFilter> {
184
203
  private pool;
185
204
  private describeIndexCache;
186
205
  private createdIndexes;
@@ -198,7 +217,7 @@ declare class PgVector extends MastraVector {
198
217
  private getMutexByName;
199
218
  private getTableName;
200
219
  private getSchemaName;
201
- transformFilter(filter?: VectorFilter): VectorFilter;
220
+ transformFilter(filter?: PGVectorFilter): PGVectorFilter;
202
221
  getIndexInfo({ indexName }: DescribeIndexParams): Promise<PGIndexStats>;
203
222
  query({ indexName, queryVector, topK, filter, includeVector, minScore, ef, probes, }: PgQueryVectorParams): Promise<QueryResult[]>;
204
223
  upsert({ indexName, vectors, metadata, ids }: UpsertVectorParams): Promise<string[]>;
@@ -252,6 +271,8 @@ declare const PGVECTOR_PROMPT = "When querying PG Vector, you can ONLY use the o
252
271
  export { PGVECTOR_PROMPT }
253
272
  export { PGVECTOR_PROMPT as PGVECTOR_PROMPT_alias_1 }
254
273
 
274
+ export declare type PGVectorFilter = VectorFilter<keyof PGOperatorValueMap, PGOperatorValueMap, LogicalOperatorValueMap, PGBlacklisted, PGFilterValue>;
275
+
255
276
  declare type PostgresConfig = {
256
277
  schemaName?: string;
257
278
  } & ({
@@ -276,6 +297,7 @@ declare class PostgresStore extends MastraStorage {
276
297
  constructor(config: PostgresConfig);
277
298
  get supports(): {
278
299
  selectByIncludeResourceScope: boolean;
300
+ resourceWorkingMemory: boolean;
279
301
  };
280
302
  private getTableName;
281
303
  private getSchemaName;
@@ -422,6 +444,17 @@ declare class PostgresStore extends MastraStorage {
422
444
  };
423
445
  })[];
424
446
  }): Promise<MastraMessageV2[]>;
447
+ getResourceById({ resourceId }: {
448
+ resourceId: string;
449
+ }): Promise<StorageResourceType | null>;
450
+ saveResource({ resource }: {
451
+ resource: StorageResourceType;
452
+ }): Promise<StorageResourceType>;
453
+ updateResource({ resourceId, workingMemory, metadata, }: {
454
+ resourceId: string;
455
+ workingMemory?: string;
456
+ metadata?: Record<string, unknown>;
457
+ }): Promise<StorageResourceType>;
425
458
  }
426
459
  export { PostgresStore }
427
460
  export { PostgresStore as PostgresStore_alias_1 }
@@ -1,4 +1,5 @@
1
1
  import { BaseFilterTranslator } from '@mastra/core/vector/filter';
2
+ import type { BlacklistedRootOperators } from '@mastra/core/vector/filter';
2
3
  import type { CreateIndexParams } from '@mastra/core/vector';
3
4
  import type { DeleteIndexParams } from '@mastra/core/vector';
4
5
  import type { DeleteVectorParams } from '@mastra/core/vector';
@@ -6,12 +7,14 @@ import type { DescribeIndexParams } from '@mastra/core/vector';
6
7
  import type { EvalRow } from '@mastra/core/storage';
7
8
  import type { IndexStats } from '@mastra/core/vector';
8
9
  import type { ISSLConfig } from 'pg-promise/typescript/pg-subset';
10
+ import type { LogicalOperatorValueMap } from '@mastra/core/vector/filter';
9
11
  import type { MastraMessageContentV2 } from '@mastra/core/agent';
10
12
  import type { MastraMessageV1 } from '@mastra/core/memory';
11
13
  import type { MastraMessageV2 } from '@mastra/core/agent';
12
14
  import { MastraStorage } from '@mastra/core/storage';
13
15
  import { MastraVector } from '@mastra/core/vector';
14
16
  import type { OperatorSupport } from '@mastra/core/vector/filter';
17
+ import type { OperatorValueMap } from '@mastra/core/vector/filter';
15
18
  import type { PaginationArgs } from '@mastra/core/storage';
16
19
  import type { PaginationInfo } from '@mastra/core/storage';
17
20
  import pg from 'pg';
@@ -19,10 +22,12 @@ import type { QueryResult } from '@mastra/core/vector';
19
22
  import type { QueryVectorParams } from '@mastra/core/vector';
20
23
  import type { StorageColumn } from '@mastra/core/storage';
21
24
  import type { StorageGetMessagesArg } from '@mastra/core/storage';
25
+ import type { StorageResourceType } from '@mastra/core/storage';
22
26
  import type { StorageThreadType } from '@mastra/core/memory';
23
27
  import type { TABLE_NAMES } from '@mastra/core/storage';
24
28
  import type { UpdateVectorParams } from '@mastra/core/vector';
25
29
  import type { UpsertVectorParams } from '@mastra/core/vector';
30
+ import type { VectorFieldValue } from '@mastra/core/vector/filter';
26
31
  import type { VectorFilter } from '@mastra/core/vector/filter';
27
32
  import type { WorkflowRun } from '@mastra/core/storage';
28
33
  import type { WorkflowRuns } from '@mastra/core/storage';
@@ -61,7 +66,7 @@ export declare const baseTestConfigs: {
61
66
  }[];
62
67
  };
63
68
 
64
- export declare function buildFilterQuery(filter: VectorFilter, minScore: number, topK: number): FilterResult;
69
+ export declare function buildFilterQuery(filter: PGVectorFilter, minScore: number, topK: number): FilterResult;
65
70
 
66
71
  export declare const calculateRecall: (actual: number[], expected: number[], k: number) => number;
67
72
 
@@ -126,6 +131,8 @@ declare interface IVFConfig {
126
131
 
127
132
  export declare function measureLatency<T>(fn: () => Promise<T>): Promise<[number, T]>;
128
133
 
134
+ declare type PGBlacklisted = BlacklistedRootOperators | '$contains' | '$size';
135
+
129
136
  declare interface PgCreateIndexParams extends CreateIndexParams {
130
137
  indexConfig?: IndexConfig;
131
138
  buildIndex?: boolean;
@@ -147,13 +154,15 @@ declare interface PgDefineIndexParams {
147
154
  * - Can take either a single condition or an array of conditions
148
155
  *
149
156
  */
150
- export declare class PGFilterTranslator extends BaseFilterTranslator {
157
+ export declare class PGFilterTranslator extends BaseFilterTranslator<PGVectorFilter> {
151
158
  protected getSupportedOperators(): OperatorSupport;
152
- translate(filter?: VectorFilter): VectorFilter;
159
+ translate(filter?: PGVectorFilter): PGVectorFilter;
153
160
  private translateNode;
154
161
  private translateRegexPattern;
155
162
  }
156
163
 
164
+ declare type PGFilterValue = VectorFieldValue | RegExp;
165
+
157
166
  declare interface PGIndexStats extends IndexStats {
158
167
  type: IndexType;
159
168
  config: {
@@ -166,7 +175,17 @@ declare interface PGIndexStats extends IndexStats {
166
175
  export { PGIndexStats }
167
176
  export { PGIndexStats as PGIndexStats_alias_1 }
168
177
 
169
- declare interface PgQueryVectorParams extends QueryVectorParams {
178
+ declare type PGOperatorValueMap = Omit<OperatorValueMap, '$in' | '$all' | '$nin' | '$eq' | '$ne'> & {
179
+ $size: number;
180
+ $contains: VectorFieldValue | Record<string, unknown>;
181
+ $all: VectorFieldValue;
182
+ $in: VectorFieldValue;
183
+ $nin: VectorFieldValue;
184
+ $eq: VectorFieldValue;
185
+ $ne: VectorFieldValue;
186
+ };
187
+
188
+ declare interface PgQueryVectorParams extends QueryVectorParams<PGVectorFilter> {
170
189
  minScore?: number;
171
190
  /**
172
191
  * HNSW search parameter. Controls the size of the dynamic candidate
@@ -180,7 +199,7 @@ declare interface PgQueryVectorParams extends QueryVectorParams {
180
199
  probes?: number;
181
200
  }
182
201
 
183
- declare class PgVector extends MastraVector {
202
+ declare class PgVector extends MastraVector<PGVectorFilter> {
184
203
  private pool;
185
204
  private describeIndexCache;
186
205
  private createdIndexes;
@@ -198,7 +217,7 @@ declare class PgVector extends MastraVector {
198
217
  private getMutexByName;
199
218
  private getTableName;
200
219
  private getSchemaName;
201
- transformFilter(filter?: VectorFilter): VectorFilter;
220
+ transformFilter(filter?: PGVectorFilter): PGVectorFilter;
202
221
  getIndexInfo({ indexName }: DescribeIndexParams): Promise<PGIndexStats>;
203
222
  query({ indexName, queryVector, topK, filter, includeVector, minScore, ef, probes, }: PgQueryVectorParams): Promise<QueryResult[]>;
204
223
  upsert({ indexName, vectors, metadata, ids }: UpsertVectorParams): Promise<string[]>;
@@ -252,6 +271,8 @@ declare const PGVECTOR_PROMPT = "When querying PG Vector, you can ONLY use the o
252
271
  export { PGVECTOR_PROMPT }
253
272
  export { PGVECTOR_PROMPT as PGVECTOR_PROMPT_alias_1 }
254
273
 
274
+ export declare type PGVectorFilter = VectorFilter<keyof PGOperatorValueMap, PGOperatorValueMap, LogicalOperatorValueMap, PGBlacklisted, PGFilterValue>;
275
+
255
276
  declare type PostgresConfig = {
256
277
  schemaName?: string;
257
278
  } & ({
@@ -276,6 +297,7 @@ declare class PostgresStore extends MastraStorage {
276
297
  constructor(config: PostgresConfig);
277
298
  get supports(): {
278
299
  selectByIncludeResourceScope: boolean;
300
+ resourceWorkingMemory: boolean;
279
301
  };
280
302
  private getTableName;
281
303
  private getSchemaName;
@@ -422,6 +444,17 @@ declare class PostgresStore extends MastraStorage {
422
444
  };
423
445
  })[];
424
446
  }): Promise<MastraMessageV2[]>;
447
+ getResourceById({ resourceId }: {
448
+ resourceId: string;
449
+ }): Promise<StorageResourceType | null>;
450
+ saveResource({ resource }: {
451
+ resource: StorageResourceType;
452
+ }): Promise<StorageResourceType>;
453
+ updateResource({ resourceId, workingMemory, metadata, }: {
454
+ resourceId: string;
455
+ workingMemory?: string;
456
+ metadata?: Record<string, unknown>;
457
+ }): Promise<StorageResourceType>;
425
458
  }
426
459
  export { PostgresStore }
427
460
  export { PostgresStore as PostgresStore_alias_1 }
package/dist/index.cjs CHANGED
@@ -45,10 +45,10 @@ var PGFilterTranslator = class extends filter.BaseFilterTranslator {
45
45
  }
46
46
  const entries = Object.entries(node);
47
47
  const result = {};
48
- if ("$options" in node && !("$regex" in node)) {
48
+ if (node && "$options" in node && !("$regex" in node)) {
49
49
  throw new Error("$options is not valid without $regex");
50
50
  }
51
- if ("$regex" in node) {
51
+ if (node && "$regex" in node) {
52
52
  const options = node.$options || "";
53
53
  return withPath(this.translateRegexPattern(node.$regex, options));
54
54
  }
@@ -1154,7 +1154,8 @@ var PostgresStore = class extends storage.MastraStorage {
1154
1154
  }
1155
1155
  get supports() {
1156
1156
  return {
1157
- selectByIncludeResourceScope: true
1157
+ selectByIncludeResourceScope: true,
1158
+ resourceWorkingMemory: true
1158
1159
  };
1159
1160
  }
1160
1161
  getTableName(indexName) {
@@ -1919,7 +1920,7 @@ var PostgresStore = class extends storage.MastraStorage {
1919
1920
  }
1920
1921
  }
1921
1922
  try {
1922
- const perPage = perPageInput !== void 0 ? perPageInput : 40;
1923
+ const perPage = perPageInput !== void 0 ? perPageInput : this.resolveMessageLimit({ last: selectBy?.last, defaultLimit: 40 });
1923
1924
  const currentOffset = page * perPage;
1924
1925
  const conditions = [`thread_id = $1`];
1925
1926
  const queryParams = [threadId];
@@ -1936,7 +1937,7 @@ var PostgresStore = class extends storage.MastraStorage {
1936
1937
  const countQuery = `SELECT COUNT(*) FROM ${this.getTableName(storage.TABLE_MESSAGES)} ${whereClause}`;
1937
1938
  const countResult = await this.db.one(countQuery, queryParams);
1938
1939
  const total = parseInt(countResult.count, 10);
1939
- if (total === 0) {
1940
+ if (total === 0 && messages.length === 0) {
1940
1941
  return {
1941
1942
  messages: [],
1942
1943
  total: 0,
@@ -1945,10 +1946,13 @@ var PostgresStore = class extends storage.MastraStorage {
1945
1946
  hasMore: false
1946
1947
  };
1947
1948
  }
1949
+ const excludeIds = messages.map((m) => m.id);
1950
+ const excludeIdsParam = excludeIds.map((_, idx) => `$${idx + paramIndex}`).join(", ");
1951
+ paramIndex += excludeIds.length;
1948
1952
  const dataQuery = `${selectStatement} FROM ${this.getTableName(
1949
1953
  storage.TABLE_MESSAGES
1950
- )} ${whereClause} ${orderByStatement} LIMIT $${paramIndex++} OFFSET $${paramIndex++}`;
1951
- const rows = await this.db.manyOrNone(dataQuery, [...queryParams, perPage, currentOffset]);
1954
+ )} ${whereClause} ${excludeIds.length ? `AND id NOT IN (${excludeIdsParam})` : ""}${orderByStatement} LIMIT $${paramIndex++} OFFSET $${paramIndex++}`;
1955
+ const rows = await this.db.manyOrNone(dataQuery, [...queryParams, ...excludeIds, perPage, currentOffset]);
1952
1956
  messages.push(...rows || []);
1953
1957
  const list = new agent.MessageList().add(messages, "memory");
1954
1958
  const messagesToReturn = format === `v2` ? list.get.all.v2() : list.get.all.v1();
@@ -2018,7 +2022,13 @@ var PostgresStore = class extends storage.MastraStorage {
2018
2022
  }
2019
2023
  return t.none(
2020
2024
  `INSERT INTO ${this.getTableName(storage.TABLE_MESSAGES)} (id, thread_id, content, "createdAt", role, type, "resourceId")
2021
- VALUES ($1, $2, $3, $4, $5, $6, $7)`,
2025
+ VALUES ($1, $2, $3, $4, $5, $6, $7)
2026
+ ON CONFLICT (id) DO UPDATE SET
2027
+ thread_id = EXCLUDED.thread_id,
2028
+ content = EXCLUDED.content,
2029
+ role = EXCLUDED.role,
2030
+ type = EXCLUDED.type,
2031
+ "resourceId" = EXCLUDED."resourceId"`,
2022
2032
  [
2023
2033
  message.id,
2024
2034
  message.threadId,
@@ -2431,6 +2441,82 @@ var PostgresStore = class extends storage.MastraStorage {
2431
2441
  return message;
2432
2442
  });
2433
2443
  }
2444
+ async getResourceById({ resourceId }) {
2445
+ const tableName = this.getTableName(storage.TABLE_RESOURCES);
2446
+ const result = await this.db.oneOrNone(`SELECT * FROM ${tableName} WHERE id = $1`, [
2447
+ resourceId
2448
+ ]);
2449
+ if (!result) {
2450
+ return null;
2451
+ }
2452
+ return {
2453
+ ...result,
2454
+ // Ensure workingMemory is always returned as a string, regardless of automatic parsing
2455
+ workingMemory: typeof result.workingMemory === "object" ? JSON.stringify(result.workingMemory) : result.workingMemory,
2456
+ metadata: typeof result.metadata === "string" ? JSON.parse(result.metadata) : result.metadata
2457
+ };
2458
+ }
2459
+ async saveResource({ resource }) {
2460
+ const tableName = this.getTableName(storage.TABLE_RESOURCES);
2461
+ await this.db.none(
2462
+ `INSERT INTO ${tableName} (id, "workingMemory", metadata, "createdAt", "updatedAt")
2463
+ VALUES ($1, $2, $3, $4, $5)`,
2464
+ [
2465
+ resource.id,
2466
+ resource.workingMemory,
2467
+ JSON.stringify(resource.metadata),
2468
+ resource.createdAt.toISOString(),
2469
+ resource.updatedAt.toISOString()
2470
+ ]
2471
+ );
2472
+ return resource;
2473
+ }
2474
+ async updateResource({
2475
+ resourceId,
2476
+ workingMemory,
2477
+ metadata
2478
+ }) {
2479
+ const existingResource = await this.getResourceById({ resourceId });
2480
+ if (!existingResource) {
2481
+ const newResource = {
2482
+ id: resourceId,
2483
+ workingMemory,
2484
+ metadata: metadata || {},
2485
+ createdAt: /* @__PURE__ */ new Date(),
2486
+ updatedAt: /* @__PURE__ */ new Date()
2487
+ };
2488
+ return this.saveResource({ resource: newResource });
2489
+ }
2490
+ const updatedResource = {
2491
+ ...existingResource,
2492
+ workingMemory: workingMemory !== void 0 ? workingMemory : existingResource.workingMemory,
2493
+ metadata: {
2494
+ ...existingResource.metadata,
2495
+ ...metadata
2496
+ },
2497
+ updatedAt: /* @__PURE__ */ new Date()
2498
+ };
2499
+ const tableName = this.getTableName(storage.TABLE_RESOURCES);
2500
+ const updates = [];
2501
+ const values = [];
2502
+ let paramIndex = 1;
2503
+ if (workingMemory !== void 0) {
2504
+ updates.push(`"workingMemory" = $${paramIndex}`);
2505
+ values.push(workingMemory);
2506
+ paramIndex++;
2507
+ }
2508
+ if (metadata) {
2509
+ updates.push(`metadata = $${paramIndex}`);
2510
+ values.push(JSON.stringify(updatedResource.metadata));
2511
+ paramIndex++;
2512
+ }
2513
+ updates.push(`"updatedAt" = $${paramIndex}`);
2514
+ values.push(updatedResource.updatedAt.toISOString());
2515
+ paramIndex++;
2516
+ values.push(resourceId);
2517
+ await this.db.none(`UPDATE ${tableName} SET ${updates.join(", ")} WHERE id = $${paramIndex}`, values);
2518
+ return updatedResource;
2519
+ }
2434
2520
  };
2435
2521
 
2436
2522
  // src/vector/prompt.ts
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ import pg from 'pg';
6
6
  import xxhash from 'xxhash-wasm';
7
7
  import { BaseFilterTranslator } from '@mastra/core/vector/filter';
8
8
  import { MessageList } from '@mastra/core/agent';
9
- import { MastraStorage, TABLE_EVALS, TABLE_TRACES, TABLE_WORKFLOW_SNAPSHOT, TABLE_THREADS, TABLE_MESSAGES } from '@mastra/core/storage';
9
+ import { MastraStorage, TABLE_EVALS, TABLE_TRACES, TABLE_WORKFLOW_SNAPSHOT, TABLE_THREADS, TABLE_MESSAGES, TABLE_RESOURCES } from '@mastra/core/storage';
10
10
  import pgPromise from 'pg-promise';
11
11
 
12
12
  // src/vector/index.ts
@@ -37,10 +37,10 @@ var PGFilterTranslator = class extends BaseFilterTranslator {
37
37
  }
38
38
  const entries = Object.entries(node);
39
39
  const result = {};
40
- if ("$options" in node && !("$regex" in node)) {
40
+ if (node && "$options" in node && !("$regex" in node)) {
41
41
  throw new Error("$options is not valid without $regex");
42
42
  }
43
- if ("$regex" in node) {
43
+ if (node && "$regex" in node) {
44
44
  const options = node.$options || "";
45
45
  return withPath(this.translateRegexPattern(node.$regex, options));
46
46
  }
@@ -1146,7 +1146,8 @@ var PostgresStore = class extends MastraStorage {
1146
1146
  }
1147
1147
  get supports() {
1148
1148
  return {
1149
- selectByIncludeResourceScope: true
1149
+ selectByIncludeResourceScope: true,
1150
+ resourceWorkingMemory: true
1150
1151
  };
1151
1152
  }
1152
1153
  getTableName(indexName) {
@@ -1911,7 +1912,7 @@ var PostgresStore = class extends MastraStorage {
1911
1912
  }
1912
1913
  }
1913
1914
  try {
1914
- const perPage = perPageInput !== void 0 ? perPageInput : 40;
1915
+ const perPage = perPageInput !== void 0 ? perPageInput : this.resolveMessageLimit({ last: selectBy?.last, defaultLimit: 40 });
1915
1916
  const currentOffset = page * perPage;
1916
1917
  const conditions = [`thread_id = $1`];
1917
1918
  const queryParams = [threadId];
@@ -1928,7 +1929,7 @@ var PostgresStore = class extends MastraStorage {
1928
1929
  const countQuery = `SELECT COUNT(*) FROM ${this.getTableName(TABLE_MESSAGES)} ${whereClause}`;
1929
1930
  const countResult = await this.db.one(countQuery, queryParams);
1930
1931
  const total = parseInt(countResult.count, 10);
1931
- if (total === 0) {
1932
+ if (total === 0 && messages.length === 0) {
1932
1933
  return {
1933
1934
  messages: [],
1934
1935
  total: 0,
@@ -1937,10 +1938,13 @@ var PostgresStore = class extends MastraStorage {
1937
1938
  hasMore: false
1938
1939
  };
1939
1940
  }
1941
+ const excludeIds = messages.map((m) => m.id);
1942
+ const excludeIdsParam = excludeIds.map((_, idx) => `$${idx + paramIndex}`).join(", ");
1943
+ paramIndex += excludeIds.length;
1940
1944
  const dataQuery = `${selectStatement} FROM ${this.getTableName(
1941
1945
  TABLE_MESSAGES
1942
- )} ${whereClause} ${orderByStatement} LIMIT $${paramIndex++} OFFSET $${paramIndex++}`;
1943
- const rows = await this.db.manyOrNone(dataQuery, [...queryParams, perPage, currentOffset]);
1946
+ )} ${whereClause} ${excludeIds.length ? `AND id NOT IN (${excludeIdsParam})` : ""}${orderByStatement} LIMIT $${paramIndex++} OFFSET $${paramIndex++}`;
1947
+ const rows = await this.db.manyOrNone(dataQuery, [...queryParams, ...excludeIds, perPage, currentOffset]);
1944
1948
  messages.push(...rows || []);
1945
1949
  const list = new MessageList().add(messages, "memory");
1946
1950
  const messagesToReturn = format === `v2` ? list.get.all.v2() : list.get.all.v1();
@@ -2010,7 +2014,13 @@ var PostgresStore = class extends MastraStorage {
2010
2014
  }
2011
2015
  return t.none(
2012
2016
  `INSERT INTO ${this.getTableName(TABLE_MESSAGES)} (id, thread_id, content, "createdAt", role, type, "resourceId")
2013
- VALUES ($1, $2, $3, $4, $5, $6, $7)`,
2017
+ VALUES ($1, $2, $3, $4, $5, $6, $7)
2018
+ ON CONFLICT (id) DO UPDATE SET
2019
+ thread_id = EXCLUDED.thread_id,
2020
+ content = EXCLUDED.content,
2021
+ role = EXCLUDED.role,
2022
+ type = EXCLUDED.type,
2023
+ "resourceId" = EXCLUDED."resourceId"`,
2014
2024
  [
2015
2025
  message.id,
2016
2026
  message.threadId,
@@ -2423,6 +2433,82 @@ var PostgresStore = class extends MastraStorage {
2423
2433
  return message;
2424
2434
  });
2425
2435
  }
2436
+ async getResourceById({ resourceId }) {
2437
+ const tableName = this.getTableName(TABLE_RESOURCES);
2438
+ const result = await this.db.oneOrNone(`SELECT * FROM ${tableName} WHERE id = $1`, [
2439
+ resourceId
2440
+ ]);
2441
+ if (!result) {
2442
+ return null;
2443
+ }
2444
+ return {
2445
+ ...result,
2446
+ // Ensure workingMemory is always returned as a string, regardless of automatic parsing
2447
+ workingMemory: typeof result.workingMemory === "object" ? JSON.stringify(result.workingMemory) : result.workingMemory,
2448
+ metadata: typeof result.metadata === "string" ? JSON.parse(result.metadata) : result.metadata
2449
+ };
2450
+ }
2451
+ async saveResource({ resource }) {
2452
+ const tableName = this.getTableName(TABLE_RESOURCES);
2453
+ await this.db.none(
2454
+ `INSERT INTO ${tableName} (id, "workingMemory", metadata, "createdAt", "updatedAt")
2455
+ VALUES ($1, $2, $3, $4, $5)`,
2456
+ [
2457
+ resource.id,
2458
+ resource.workingMemory,
2459
+ JSON.stringify(resource.metadata),
2460
+ resource.createdAt.toISOString(),
2461
+ resource.updatedAt.toISOString()
2462
+ ]
2463
+ );
2464
+ return resource;
2465
+ }
2466
+ async updateResource({
2467
+ resourceId,
2468
+ workingMemory,
2469
+ metadata
2470
+ }) {
2471
+ const existingResource = await this.getResourceById({ resourceId });
2472
+ if (!existingResource) {
2473
+ const newResource = {
2474
+ id: resourceId,
2475
+ workingMemory,
2476
+ metadata: metadata || {},
2477
+ createdAt: /* @__PURE__ */ new Date(),
2478
+ updatedAt: /* @__PURE__ */ new Date()
2479
+ };
2480
+ return this.saveResource({ resource: newResource });
2481
+ }
2482
+ const updatedResource = {
2483
+ ...existingResource,
2484
+ workingMemory: workingMemory !== void 0 ? workingMemory : existingResource.workingMemory,
2485
+ metadata: {
2486
+ ...existingResource.metadata,
2487
+ ...metadata
2488
+ },
2489
+ updatedAt: /* @__PURE__ */ new Date()
2490
+ };
2491
+ const tableName = this.getTableName(TABLE_RESOURCES);
2492
+ const updates = [];
2493
+ const values = [];
2494
+ let paramIndex = 1;
2495
+ if (workingMemory !== void 0) {
2496
+ updates.push(`"workingMemory" = $${paramIndex}`);
2497
+ values.push(workingMemory);
2498
+ paramIndex++;
2499
+ }
2500
+ if (metadata) {
2501
+ updates.push(`metadata = $${paramIndex}`);
2502
+ values.push(JSON.stringify(updatedResource.metadata));
2503
+ paramIndex++;
2504
+ }
2505
+ updates.push(`"updatedAt" = $${paramIndex}`);
2506
+ values.push(updatedResource.updatedAt.toISOString());
2507
+ paramIndex++;
2508
+ values.push(resourceId);
2509
+ await this.db.none(`UPDATE ${tableName} SET ${updates.join(", ")} WHERE id = $${paramIndex}`, values);
2510
+ return updatedResource;
2511
+ }
2426
2512
  };
2427
2513
 
2428
2514
  // src/vector/prompt.ts