@mastra/pg 0.11.1-alpha.0 → 0.11.1-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/.turbo/turbo-build.log +7 -7
- package/CHANGELOG.md +28 -0
- package/dist/_tsup-dts-rollup.d.cts +40 -6
- package/dist/_tsup-dts-rollup.d.ts +40 -6
- package/dist/index.cjs +808 -255
- package/dist/index.js +785 -232
- package/package.json +4 -4
- package/src/storage/index.test.ts +428 -35
- package/src/storage/index.ts +596 -197
- package/src/vector/filter.test.ts +12 -12
- package/src/vector/filter.ts +36 -7
- package/src/vector/index.test.ts +2 -2
- package/src/vector/index.ts +283 -90
- package/src/vector/sql-builder.ts +2 -1
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { MastraError, ErrorCategory, ErrorDomain } from '@mastra/core/error';
|
|
1
2
|
import { parseSqlIdentifier, parseFieldKey } from '@mastra/core/utils';
|
|
2
3
|
import { MastraVector } from '@mastra/core/vector';
|
|
3
4
|
import { Mutex } from 'async-mutex';
|
|
@@ -5,7 +6,7 @@ import pg from 'pg';
|
|
|
5
6
|
import xxhash from 'xxhash-wasm';
|
|
6
7
|
import { BaseFilterTranslator } from '@mastra/core/vector/filter';
|
|
7
8
|
import { MessageList } from '@mastra/core/agent';
|
|
8
|
-
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';
|
|
9
10
|
import pgPromise from 'pg-promise';
|
|
10
11
|
|
|
11
12
|
// src/vector/index.ts
|
|
@@ -36,10 +37,10 @@ var PGFilterTranslator = class extends BaseFilterTranslator {
|
|
|
36
37
|
}
|
|
37
38
|
const entries = Object.entries(node);
|
|
38
39
|
const result = {};
|
|
39
|
-
if ("$options" in node && !("$regex" in node)) {
|
|
40
|
+
if (node && "$options" in node && !("$regex" in node)) {
|
|
40
41
|
throw new Error("$options is not valid without $regex");
|
|
41
42
|
}
|
|
42
|
-
if ("$regex" in node) {
|
|
43
|
+
if (node && "$regex" in node) {
|
|
43
44
|
const options = node.$options || "";
|
|
44
45
|
return withPath(this.translateRegexPattern(node.$regex, options));
|
|
45
46
|
}
|
|
@@ -368,43 +369,57 @@ var PgVector = class extends MastraVector {
|
|
|
368
369
|
schemaName,
|
|
369
370
|
pgPoolOptions
|
|
370
371
|
}) {
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
super();
|
|
377
|
-
this.schema = schemaName;
|
|
378
|
-
const basePool = new pg.Pool({
|
|
379
|
-
connectionString,
|
|
380
|
-
max: 20,
|
|
381
|
-
// Maximum number of clients in the pool
|
|
382
|
-
idleTimeoutMillis: 3e4,
|
|
383
|
-
// Close idle connections after 30 seconds
|
|
384
|
-
connectionTimeoutMillis: 2e3,
|
|
385
|
-
// Fail fast if can't connect
|
|
386
|
-
...pgPoolOptions
|
|
387
|
-
});
|
|
388
|
-
const telemetry = this.__getTelemetry();
|
|
389
|
-
this.pool = telemetry?.traceClass(basePool, {
|
|
390
|
-
spanNamePrefix: "pg-vector",
|
|
391
|
-
attributes: {
|
|
392
|
-
"vector.type": "postgres"
|
|
372
|
+
try {
|
|
373
|
+
if (!connectionString || connectionString.trim() === "") {
|
|
374
|
+
throw new Error(
|
|
375
|
+
"PgVector: connectionString must be provided and cannot be empty. Passing an empty string may cause fallback to local Postgres defaults."
|
|
376
|
+
);
|
|
393
377
|
}
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
const
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
this.createdIndexes.set(indexName, key);
|
|
378
|
+
super();
|
|
379
|
+
this.schema = schemaName;
|
|
380
|
+
const basePool = new pg.Pool({
|
|
381
|
+
connectionString,
|
|
382
|
+
max: 20,
|
|
383
|
+
// Maximum number of clients in the pool
|
|
384
|
+
idleTimeoutMillis: 3e4,
|
|
385
|
+
// Close idle connections after 30 seconds
|
|
386
|
+
connectionTimeoutMillis: 2e3,
|
|
387
|
+
// Fail fast if can't connect
|
|
388
|
+
...pgPoolOptions
|
|
406
389
|
});
|
|
407
|
-
|
|
390
|
+
const telemetry = this.__getTelemetry();
|
|
391
|
+
this.pool = telemetry?.traceClass(basePool, {
|
|
392
|
+
spanNamePrefix: "pg-vector",
|
|
393
|
+
attributes: {
|
|
394
|
+
"vector.type": "postgres"
|
|
395
|
+
}
|
|
396
|
+
}) ?? basePool;
|
|
397
|
+
void (async () => {
|
|
398
|
+
const existingIndexes = await this.listIndexes();
|
|
399
|
+
void existingIndexes.map(async (indexName) => {
|
|
400
|
+
const info = await this.getIndexInfo({ indexName });
|
|
401
|
+
const key = await this.getIndexCacheKey({
|
|
402
|
+
indexName,
|
|
403
|
+
metric: info.metric,
|
|
404
|
+
dimension: info.dimension,
|
|
405
|
+
type: info.type
|
|
406
|
+
});
|
|
407
|
+
this.createdIndexes.set(indexName, key);
|
|
408
|
+
});
|
|
409
|
+
})();
|
|
410
|
+
} catch (error) {
|
|
411
|
+
throw new MastraError(
|
|
412
|
+
{
|
|
413
|
+
id: "MASTRA_STORAGE_PG_VECTOR_INITIALIZATION_FAILED",
|
|
414
|
+
domain: ErrorDomain.MASTRA_VECTOR,
|
|
415
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
416
|
+
details: {
|
|
417
|
+
schemaName: schemaName ?? ""
|
|
418
|
+
}
|
|
419
|
+
},
|
|
420
|
+
error
|
|
421
|
+
);
|
|
422
|
+
}
|
|
408
423
|
}
|
|
409
424
|
getMutexByName(indexName) {
|
|
410
425
|
if (!this.mutexesByName.has(indexName)) this.mutexesByName.set(indexName, new Mutex());
|
|
@@ -443,11 +458,27 @@ var PgVector = class extends MastraVector {
|
|
|
443
458
|
ef,
|
|
444
459
|
probes
|
|
445
460
|
}) {
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
461
|
+
try {
|
|
462
|
+
if (!Number.isInteger(topK) || topK <= 0) {
|
|
463
|
+
throw new Error("topK must be a positive integer");
|
|
464
|
+
}
|
|
465
|
+
if (!Array.isArray(queryVector) || !queryVector.every((x) => typeof x === "number" && Number.isFinite(x))) {
|
|
466
|
+
throw new Error("queryVector must be an array of finite numbers");
|
|
467
|
+
}
|
|
468
|
+
} catch (error) {
|
|
469
|
+
const mastraError = new MastraError(
|
|
470
|
+
{
|
|
471
|
+
id: "MASTRA_STORAGE_PG_VECTOR_QUERY_INVALID_INPUT",
|
|
472
|
+
domain: ErrorDomain.MASTRA_VECTOR,
|
|
473
|
+
category: ErrorCategory.USER,
|
|
474
|
+
details: {
|
|
475
|
+
indexName
|
|
476
|
+
}
|
|
477
|
+
},
|
|
478
|
+
error
|
|
479
|
+
);
|
|
480
|
+
this.logger?.trackException(mastraError);
|
|
481
|
+
throw mastraError;
|
|
451
482
|
}
|
|
452
483
|
const client = await this.pool.connect();
|
|
453
484
|
try {
|
|
@@ -486,6 +517,20 @@ var PgVector = class extends MastraVector {
|
|
|
486
517
|
metadata,
|
|
487
518
|
...includeVector && embedding && { vector: JSON.parse(embedding) }
|
|
488
519
|
}));
|
|
520
|
+
} catch (error) {
|
|
521
|
+
const mastraError = new MastraError(
|
|
522
|
+
{
|
|
523
|
+
id: "MASTRA_STORAGE_PG_VECTOR_QUERY_FAILED",
|
|
524
|
+
domain: ErrorDomain.MASTRA_VECTOR,
|
|
525
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
526
|
+
details: {
|
|
527
|
+
indexName
|
|
528
|
+
}
|
|
529
|
+
},
|
|
530
|
+
error
|
|
531
|
+
);
|
|
532
|
+
this.logger?.trackException(mastraError);
|
|
533
|
+
throw mastraError;
|
|
489
534
|
} finally {
|
|
490
535
|
client.release();
|
|
491
536
|
}
|
|
@@ -516,12 +561,37 @@ var PgVector = class extends MastraVector {
|
|
|
516
561
|
const match = error.message.match(/expected (\d+) dimensions, not (\d+)/);
|
|
517
562
|
if (match) {
|
|
518
563
|
const [, expected, actual] = match;
|
|
519
|
-
|
|
520
|
-
|
|
564
|
+
const mastraError2 = new MastraError(
|
|
565
|
+
{
|
|
566
|
+
id: "MASTRA_STORAGE_PG_VECTOR_UPSERT_INVALID_INPUT",
|
|
567
|
+
domain: ErrorDomain.MASTRA_VECTOR,
|
|
568
|
+
category: ErrorCategory.USER,
|
|
569
|
+
text: `Vector dimension mismatch: Index "${indexName}" expects ${expected} dimensions but got ${actual} dimensions. Either use a matching embedding model or delete and recreate the index with the new dimension.`,
|
|
570
|
+
details: {
|
|
571
|
+
indexName,
|
|
572
|
+
expected: expected ?? "",
|
|
573
|
+
actual: actual ?? ""
|
|
574
|
+
}
|
|
575
|
+
},
|
|
576
|
+
error
|
|
521
577
|
);
|
|
578
|
+
this.logger?.trackException(mastraError2);
|
|
579
|
+
throw mastraError2;
|
|
522
580
|
}
|
|
523
581
|
}
|
|
524
|
-
|
|
582
|
+
const mastraError = new MastraError(
|
|
583
|
+
{
|
|
584
|
+
id: "MASTRA_STORAGE_PG_VECTOR_UPSERT_FAILED",
|
|
585
|
+
domain: ErrorDomain.MASTRA_VECTOR,
|
|
586
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
587
|
+
details: {
|
|
588
|
+
indexName
|
|
589
|
+
}
|
|
590
|
+
},
|
|
591
|
+
error
|
|
592
|
+
);
|
|
593
|
+
this.logger?.trackException(mastraError);
|
|
594
|
+
throw mastraError;
|
|
525
595
|
} finally {
|
|
526
596
|
client.release();
|
|
527
597
|
}
|
|
@@ -589,11 +659,27 @@ var PgVector = class extends MastraVector {
|
|
|
589
659
|
buildIndex = true
|
|
590
660
|
}) {
|
|
591
661
|
const { tableName } = this.getTableName(indexName);
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
662
|
+
try {
|
|
663
|
+
if (!indexName.match(/^[a-zA-Z_][a-zA-Z0-9_]*$/)) {
|
|
664
|
+
throw new Error("Invalid index name format");
|
|
665
|
+
}
|
|
666
|
+
if (!Number.isInteger(dimension) || dimension <= 0) {
|
|
667
|
+
throw new Error("Dimension must be a positive integer");
|
|
668
|
+
}
|
|
669
|
+
} catch (error) {
|
|
670
|
+
const mastraError = new MastraError(
|
|
671
|
+
{
|
|
672
|
+
id: "MASTRA_STORAGE_PG_VECTOR_CREATE_INDEX_INVALID_INPUT",
|
|
673
|
+
domain: ErrorDomain.MASTRA_VECTOR,
|
|
674
|
+
category: ErrorCategory.USER,
|
|
675
|
+
details: {
|
|
676
|
+
indexName
|
|
677
|
+
}
|
|
678
|
+
},
|
|
679
|
+
error
|
|
680
|
+
);
|
|
681
|
+
this.logger?.trackException(mastraError);
|
|
682
|
+
throw mastraError;
|
|
597
683
|
}
|
|
598
684
|
const indexCacheKey = await this.getIndexCacheKey({ indexName, dimension, type: indexConfig.type, metric });
|
|
599
685
|
if (this.cachedIndexExists(indexName, indexCacheKey)) {
|
|
@@ -626,12 +712,40 @@ var PgVector = class extends MastraVector {
|
|
|
626
712
|
} finally {
|
|
627
713
|
client.release();
|
|
628
714
|
}
|
|
715
|
+
}).catch((error) => {
|
|
716
|
+
const mastraError = new MastraError(
|
|
717
|
+
{
|
|
718
|
+
id: "MASTRA_STORAGE_PG_VECTOR_CREATE_INDEX_FAILED",
|
|
719
|
+
domain: ErrorDomain.MASTRA_VECTOR,
|
|
720
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
721
|
+
details: {
|
|
722
|
+
indexName
|
|
723
|
+
}
|
|
724
|
+
},
|
|
725
|
+
error
|
|
726
|
+
);
|
|
727
|
+
this.logger?.trackException(mastraError);
|
|
728
|
+
throw mastraError;
|
|
629
729
|
});
|
|
630
730
|
}
|
|
631
731
|
async buildIndex({ indexName, metric = "cosine", indexConfig }) {
|
|
632
732
|
const client = await this.pool.connect();
|
|
633
733
|
try {
|
|
634
734
|
await this.setupIndex({ indexName, metric, indexConfig }, client);
|
|
735
|
+
} catch (error) {
|
|
736
|
+
const mastraError = new MastraError(
|
|
737
|
+
{
|
|
738
|
+
id: "MASTRA_STORAGE_PG_VECTOR_BUILD_INDEX_FAILED",
|
|
739
|
+
domain: ErrorDomain.MASTRA_VECTOR,
|
|
740
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
741
|
+
details: {
|
|
742
|
+
indexName
|
|
743
|
+
}
|
|
744
|
+
},
|
|
745
|
+
error
|
|
746
|
+
);
|
|
747
|
+
this.logger?.trackException(mastraError);
|
|
748
|
+
throw mastraError;
|
|
635
749
|
} finally {
|
|
636
750
|
client.release();
|
|
637
751
|
}
|
|
@@ -728,6 +842,17 @@ var PgVector = class extends MastraVector {
|
|
|
728
842
|
`;
|
|
729
843
|
const vectorTables = await client.query(vectorTablesQuery, [this.schema || "public"]);
|
|
730
844
|
return vectorTables.rows.map((row) => row.table_name);
|
|
845
|
+
} catch (e) {
|
|
846
|
+
const mastraError = new MastraError(
|
|
847
|
+
{
|
|
848
|
+
id: "MASTRA_STORAGE_PG_VECTOR_LIST_INDEXES_FAILED",
|
|
849
|
+
domain: ErrorDomain.MASTRA_VECTOR,
|
|
850
|
+
category: ErrorCategory.THIRD_PARTY
|
|
851
|
+
},
|
|
852
|
+
e
|
|
853
|
+
);
|
|
854
|
+
this.logger?.trackException(mastraError);
|
|
855
|
+
throw mastraError;
|
|
731
856
|
} finally {
|
|
732
857
|
client.release();
|
|
733
858
|
}
|
|
@@ -807,7 +932,19 @@ var PgVector = class extends MastraVector {
|
|
|
807
932
|
};
|
|
808
933
|
} catch (e) {
|
|
809
934
|
await client.query("ROLLBACK");
|
|
810
|
-
|
|
935
|
+
const mastraError = new MastraError(
|
|
936
|
+
{
|
|
937
|
+
id: "MASTRA_STORAGE_PG_VECTOR_DESCRIBE_INDEX_FAILED",
|
|
938
|
+
domain: ErrorDomain.MASTRA_VECTOR,
|
|
939
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
940
|
+
details: {
|
|
941
|
+
indexName
|
|
942
|
+
}
|
|
943
|
+
},
|
|
944
|
+
e
|
|
945
|
+
);
|
|
946
|
+
this.logger?.trackException(mastraError);
|
|
947
|
+
throw mastraError;
|
|
811
948
|
} finally {
|
|
812
949
|
client.release();
|
|
813
950
|
}
|
|
@@ -820,7 +957,19 @@ var PgVector = class extends MastraVector {
|
|
|
820
957
|
this.createdIndexes.delete(indexName);
|
|
821
958
|
} catch (error) {
|
|
822
959
|
await client.query("ROLLBACK");
|
|
823
|
-
|
|
960
|
+
const mastraError = new MastraError(
|
|
961
|
+
{
|
|
962
|
+
id: "MASTRA_STORAGE_PG_VECTOR_DELETE_INDEX_FAILED",
|
|
963
|
+
domain: ErrorDomain.MASTRA_VECTOR,
|
|
964
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
965
|
+
details: {
|
|
966
|
+
indexName
|
|
967
|
+
}
|
|
968
|
+
},
|
|
969
|
+
error
|
|
970
|
+
);
|
|
971
|
+
this.logger?.trackException(mastraError);
|
|
972
|
+
throw mastraError;
|
|
824
973
|
} finally {
|
|
825
974
|
client.release();
|
|
826
975
|
}
|
|
@@ -832,7 +981,19 @@ var PgVector = class extends MastraVector {
|
|
|
832
981
|
await client.query(`TRUNCATE ${tableName}`);
|
|
833
982
|
} catch (e) {
|
|
834
983
|
await client.query("ROLLBACK");
|
|
835
|
-
|
|
984
|
+
const mastraError = new MastraError(
|
|
985
|
+
{
|
|
986
|
+
id: "MASTRA_STORAGE_PG_VECTOR_TRUNCATE_INDEX_FAILED",
|
|
987
|
+
domain: ErrorDomain.MASTRA_VECTOR,
|
|
988
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
989
|
+
details: {
|
|
990
|
+
indexName
|
|
991
|
+
}
|
|
992
|
+
},
|
|
993
|
+
e
|
|
994
|
+
);
|
|
995
|
+
this.logger?.trackException(mastraError);
|
|
996
|
+
throw mastraError;
|
|
836
997
|
} finally {
|
|
837
998
|
client.release();
|
|
838
999
|
}
|
|
@@ -851,11 +1012,12 @@ var PgVector = class extends MastraVector {
|
|
|
851
1012
|
* @throws Will throw an error if no updates are provided or if the update operation fails.
|
|
852
1013
|
*/
|
|
853
1014
|
async updateVector({ indexName, id, update }) {
|
|
854
|
-
|
|
855
|
-
throw new Error("No updates provided");
|
|
856
|
-
}
|
|
857
|
-
const client = await this.pool.connect();
|
|
1015
|
+
let client;
|
|
858
1016
|
try {
|
|
1017
|
+
if (!update.vector && !update.metadata) {
|
|
1018
|
+
throw new Error("No updates provided");
|
|
1019
|
+
}
|
|
1020
|
+
client = await this.pool.connect();
|
|
859
1021
|
let updateParts = [];
|
|
860
1022
|
let values = [id];
|
|
861
1023
|
let valueIndex = 2;
|
|
@@ -879,9 +1041,22 @@ var PgVector = class extends MastraVector {
|
|
|
879
1041
|
`;
|
|
880
1042
|
await client.query(query, values);
|
|
881
1043
|
} catch (error) {
|
|
882
|
-
|
|
1044
|
+
const mastraError = new MastraError(
|
|
1045
|
+
{
|
|
1046
|
+
id: "MASTRA_STORAGE_PG_VECTOR_UPDATE_VECTOR_FAILED",
|
|
1047
|
+
domain: ErrorDomain.MASTRA_VECTOR,
|
|
1048
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1049
|
+
details: {
|
|
1050
|
+
indexName,
|
|
1051
|
+
id
|
|
1052
|
+
}
|
|
1053
|
+
},
|
|
1054
|
+
error
|
|
1055
|
+
);
|
|
1056
|
+
this.logger?.trackException(mastraError);
|
|
1057
|
+
throw mastraError;
|
|
883
1058
|
} finally {
|
|
884
|
-
client
|
|
1059
|
+
client?.release();
|
|
885
1060
|
}
|
|
886
1061
|
}
|
|
887
1062
|
/**
|
|
@@ -892,8 +1067,9 @@ var PgVector = class extends MastraVector {
|
|
|
892
1067
|
* @throws Will throw an error if the deletion operation fails.
|
|
893
1068
|
*/
|
|
894
1069
|
async deleteVector({ indexName, id }) {
|
|
895
|
-
|
|
1070
|
+
let client;
|
|
896
1071
|
try {
|
|
1072
|
+
client = await this.pool.connect();
|
|
897
1073
|
const { tableName } = this.getTableName(indexName);
|
|
898
1074
|
const query = `
|
|
899
1075
|
DELETE FROM ${tableName}
|
|
@@ -901,9 +1077,22 @@ var PgVector = class extends MastraVector {
|
|
|
901
1077
|
`;
|
|
902
1078
|
await client.query(query, [id]);
|
|
903
1079
|
} catch (error) {
|
|
904
|
-
|
|
1080
|
+
const mastraError = new MastraError(
|
|
1081
|
+
{
|
|
1082
|
+
id: "MASTRA_STORAGE_PG_VECTOR_DELETE_VECTOR_FAILED",
|
|
1083
|
+
domain: ErrorDomain.MASTRA_VECTOR,
|
|
1084
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1085
|
+
details: {
|
|
1086
|
+
indexName,
|
|
1087
|
+
id
|
|
1088
|
+
}
|
|
1089
|
+
},
|
|
1090
|
+
error
|
|
1091
|
+
);
|
|
1092
|
+
this.logger?.trackException(mastraError);
|
|
1093
|
+
throw mastraError;
|
|
905
1094
|
} finally {
|
|
906
|
-
client
|
|
1095
|
+
client?.release();
|
|
907
1096
|
}
|
|
908
1097
|
}
|
|
909
1098
|
};
|
|
@@ -914,39 +1103,51 @@ var PostgresStore = class extends MastraStorage {
|
|
|
914
1103
|
setupSchemaPromise = null;
|
|
915
1104
|
schemaSetupComplete = void 0;
|
|
916
1105
|
constructor(config) {
|
|
917
|
-
|
|
918
|
-
if (
|
|
919
|
-
|
|
920
|
-
"PostgresStore: connectionString must be provided and cannot be empty. Passing an empty string may cause fallback to local Postgres defaults."
|
|
921
|
-
);
|
|
922
|
-
}
|
|
923
|
-
} else {
|
|
924
|
-
const required = ["host", "database", "user", "password"];
|
|
925
|
-
for (const key of required) {
|
|
926
|
-
if (!(key in config) || typeof config[key] !== "string" || config[key].trim() === "") {
|
|
1106
|
+
try {
|
|
1107
|
+
if ("connectionString" in config) {
|
|
1108
|
+
if (!config.connectionString || typeof config.connectionString !== "string" || config.connectionString.trim() === "") {
|
|
927
1109
|
throw new Error(
|
|
928
|
-
|
|
1110
|
+
"PostgresStore: connectionString must be provided and cannot be empty. Passing an empty string may cause fallback to local Postgres defaults."
|
|
929
1111
|
);
|
|
930
1112
|
}
|
|
1113
|
+
} else {
|
|
1114
|
+
const required = ["host", "database", "user", "password"];
|
|
1115
|
+
for (const key of required) {
|
|
1116
|
+
if (!(key in config) || typeof config[key] !== "string" || config[key].trim() === "") {
|
|
1117
|
+
throw new Error(
|
|
1118
|
+
`PostgresStore: ${key} must be provided and cannot be empty. Passing an empty string may cause fallback to local Postgres defaults.`
|
|
1119
|
+
);
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
931
1122
|
}
|
|
1123
|
+
super({ name: "PostgresStore" });
|
|
1124
|
+
this.pgp = pgPromise();
|
|
1125
|
+
this.schema = config.schemaName;
|
|
1126
|
+
this.db = this.pgp(
|
|
1127
|
+
`connectionString` in config ? { connectionString: config.connectionString } : {
|
|
1128
|
+
host: config.host,
|
|
1129
|
+
port: config.port,
|
|
1130
|
+
database: config.database,
|
|
1131
|
+
user: config.user,
|
|
1132
|
+
password: config.password,
|
|
1133
|
+
ssl: config.ssl
|
|
1134
|
+
}
|
|
1135
|
+
);
|
|
1136
|
+
} catch (e) {
|
|
1137
|
+
throw new MastraError(
|
|
1138
|
+
{
|
|
1139
|
+
id: "MASTRA_STORAGE_PG_STORE_INITIALIZATION_FAILED",
|
|
1140
|
+
domain: ErrorDomain.STORAGE,
|
|
1141
|
+
category: ErrorCategory.USER
|
|
1142
|
+
},
|
|
1143
|
+
e
|
|
1144
|
+
);
|
|
932
1145
|
}
|
|
933
|
-
super({ name: "PostgresStore" });
|
|
934
|
-
this.pgp = pgPromise();
|
|
935
|
-
this.schema = config.schemaName;
|
|
936
|
-
this.db = this.pgp(
|
|
937
|
-
`connectionString` in config ? { connectionString: config.connectionString } : {
|
|
938
|
-
host: config.host,
|
|
939
|
-
port: config.port,
|
|
940
|
-
database: config.database,
|
|
941
|
-
user: config.user,
|
|
942
|
-
password: config.password,
|
|
943
|
-
ssl: config.ssl
|
|
944
|
-
}
|
|
945
|
-
);
|
|
946
1146
|
}
|
|
947
1147
|
get supports() {
|
|
948
1148
|
return {
|
|
949
|
-
selectByIncludeResourceScope: true
|
|
1149
|
+
selectByIncludeResourceScope: true,
|
|
1150
|
+
resourceWorkingMemory: true
|
|
950
1151
|
};
|
|
951
1152
|
}
|
|
952
1153
|
getTableName(indexName) {
|
|
@@ -1004,9 +1205,19 @@ var PostgresStore = class extends MastraStorage {
|
|
|
1004
1205
|
}
|
|
1005
1206
|
await this.db.query("COMMIT");
|
|
1006
1207
|
} catch (error) {
|
|
1007
|
-
console.error(`Error inserting into ${tableName}:`, error);
|
|
1008
1208
|
await this.db.query("ROLLBACK");
|
|
1009
|
-
throw
|
|
1209
|
+
throw new MastraError(
|
|
1210
|
+
{
|
|
1211
|
+
id: "MASTRA_STORAGE_PG_STORE_BATCH_INSERT_FAILED",
|
|
1212
|
+
domain: ErrorDomain.STORAGE,
|
|
1213
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1214
|
+
details: {
|
|
1215
|
+
tableName,
|
|
1216
|
+
numberOfRecords: records.length
|
|
1217
|
+
}
|
|
1218
|
+
},
|
|
1219
|
+
error
|
|
1220
|
+
);
|
|
1010
1221
|
}
|
|
1011
1222
|
}
|
|
1012
1223
|
/**
|
|
@@ -1063,8 +1274,24 @@ var PostgresStore = class extends MastraStorage {
|
|
|
1063
1274
|
}
|
|
1064
1275
|
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
1065
1276
|
const countQuery = `SELECT COUNT(*) FROM ${this.getTableName(TABLE_TRACES)} ${whereClause}`;
|
|
1066
|
-
|
|
1067
|
-
|
|
1277
|
+
let total = 0;
|
|
1278
|
+
try {
|
|
1279
|
+
const countResult = await this.db.one(countQuery, queryParams);
|
|
1280
|
+
total = parseInt(countResult.count, 10);
|
|
1281
|
+
} catch (error) {
|
|
1282
|
+
throw new MastraError(
|
|
1283
|
+
{
|
|
1284
|
+
id: "MASTRA_STORAGE_PG_STORE_GET_TRACES_PAGINATED_FAILED_TO_RETRIEVE_TOTAL_COUNT",
|
|
1285
|
+
domain: ErrorDomain.STORAGE,
|
|
1286
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1287
|
+
details: {
|
|
1288
|
+
name: args.name ?? "",
|
|
1289
|
+
scope: args.scope ?? ""
|
|
1290
|
+
}
|
|
1291
|
+
},
|
|
1292
|
+
error
|
|
1293
|
+
);
|
|
1294
|
+
}
|
|
1068
1295
|
if (total === 0) {
|
|
1069
1296
|
return {
|
|
1070
1297
|
traces: [],
|
|
@@ -1078,30 +1305,45 @@ var PostgresStore = class extends MastraStorage {
|
|
|
1078
1305
|
TABLE_TRACES
|
|
1079
1306
|
)} ${whereClause} ORDER BY "createdAt" DESC LIMIT $${paramIndex++} OFFSET $${paramIndex++}`;
|
|
1080
1307
|
const finalQueryParams = [...queryParams, perPage, currentOffset];
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1308
|
+
try {
|
|
1309
|
+
const rows = await this.db.manyOrNone(dataQuery, finalQueryParams);
|
|
1310
|
+
const traces = rows.map((row) => ({
|
|
1311
|
+
id: row.id,
|
|
1312
|
+
parentSpanId: row.parentSpanId,
|
|
1313
|
+
traceId: row.traceId,
|
|
1314
|
+
name: row.name,
|
|
1315
|
+
scope: row.scope,
|
|
1316
|
+
kind: row.kind,
|
|
1317
|
+
status: row.status,
|
|
1318
|
+
events: row.events,
|
|
1319
|
+
links: row.links,
|
|
1320
|
+
attributes: row.attributes,
|
|
1321
|
+
startTime: row.startTime,
|
|
1322
|
+
endTime: row.endTime,
|
|
1323
|
+
other: row.other,
|
|
1324
|
+
createdAt: row.createdAt
|
|
1325
|
+
}));
|
|
1326
|
+
return {
|
|
1327
|
+
traces,
|
|
1328
|
+
total,
|
|
1329
|
+
page,
|
|
1330
|
+
perPage,
|
|
1331
|
+
hasMore: currentOffset + traces.length < total
|
|
1332
|
+
};
|
|
1333
|
+
} catch (error) {
|
|
1334
|
+
throw new MastraError(
|
|
1335
|
+
{
|
|
1336
|
+
id: "MASTRA_STORAGE_PG_STORE_GET_TRACES_PAGINATED_FAILED_TO_RETRIEVE_TRACES",
|
|
1337
|
+
domain: ErrorDomain.STORAGE,
|
|
1338
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1339
|
+
details: {
|
|
1340
|
+
name: args.name ?? "",
|
|
1341
|
+
scope: args.scope ?? ""
|
|
1342
|
+
}
|
|
1343
|
+
},
|
|
1344
|
+
error
|
|
1345
|
+
);
|
|
1346
|
+
}
|
|
1105
1347
|
}
|
|
1106
1348
|
async setupSchema() {
|
|
1107
1349
|
if (!this.schema || this.schemaSetupComplete) {
|
|
@@ -1176,8 +1418,17 @@ var PostgresStore = class extends MastraStorage {
|
|
|
1176
1418
|
`;
|
|
1177
1419
|
await this.db.none(sql);
|
|
1178
1420
|
} catch (error) {
|
|
1179
|
-
|
|
1180
|
-
|
|
1421
|
+
throw new MastraError(
|
|
1422
|
+
{
|
|
1423
|
+
id: "MASTRA_STORAGE_PG_STORE_CREATE_TABLE_FAILED",
|
|
1424
|
+
domain: ErrorDomain.STORAGE,
|
|
1425
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1426
|
+
details: {
|
|
1427
|
+
tableName
|
|
1428
|
+
}
|
|
1429
|
+
},
|
|
1430
|
+
error
|
|
1431
|
+
);
|
|
1181
1432
|
}
|
|
1182
1433
|
}
|
|
1183
1434
|
getDefaultValue(type) {
|
|
@@ -1216,18 +1467,34 @@ var PostgresStore = class extends MastraStorage {
|
|
|
1216
1467
|
}
|
|
1217
1468
|
}
|
|
1218
1469
|
} catch (error) {
|
|
1219
|
-
|
|
1220
|
-
|
|
1470
|
+
throw new MastraError(
|
|
1471
|
+
{
|
|
1472
|
+
id: "MASTRA_STORAGE_PG_STORE_ALTER_TABLE_FAILED",
|
|
1473
|
+
domain: ErrorDomain.STORAGE,
|
|
1474
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1475
|
+
details: {
|
|
1476
|
+
tableName
|
|
1477
|
+
}
|
|
1478
|
+
},
|
|
1479
|
+
error
|
|
1221
1480
|
);
|
|
1222
|
-
throw new Error(`Failed to alter table ${tableName}: ${error}`);
|
|
1223
1481
|
}
|
|
1224
1482
|
}
|
|
1225
1483
|
async clearTable({ tableName }) {
|
|
1226
1484
|
try {
|
|
1227
1485
|
await this.db.none(`TRUNCATE TABLE ${this.getTableName(tableName)} CASCADE`);
|
|
1228
1486
|
} catch (error) {
|
|
1229
|
-
|
|
1230
|
-
|
|
1487
|
+
throw new MastraError(
|
|
1488
|
+
{
|
|
1489
|
+
id: "MASTRA_STORAGE_PG_STORE_CLEAR_TABLE_FAILED",
|
|
1490
|
+
domain: ErrorDomain.STORAGE,
|
|
1491
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1492
|
+
details: {
|
|
1493
|
+
tableName
|
|
1494
|
+
}
|
|
1495
|
+
},
|
|
1496
|
+
error
|
|
1497
|
+
);
|
|
1231
1498
|
}
|
|
1232
1499
|
}
|
|
1233
1500
|
async insert({ tableName, record }) {
|
|
@@ -1240,8 +1507,17 @@ var PostgresStore = class extends MastraStorage {
|
|
|
1240
1507
|
values
|
|
1241
1508
|
);
|
|
1242
1509
|
} catch (error) {
|
|
1243
|
-
|
|
1244
|
-
|
|
1510
|
+
throw new MastraError(
|
|
1511
|
+
{
|
|
1512
|
+
id: "MASTRA_STORAGE_PG_STORE_INSERT_FAILED",
|
|
1513
|
+
domain: ErrorDomain.STORAGE,
|
|
1514
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1515
|
+
details: {
|
|
1516
|
+
tableName
|
|
1517
|
+
}
|
|
1518
|
+
},
|
|
1519
|
+
error
|
|
1520
|
+
);
|
|
1245
1521
|
}
|
|
1246
1522
|
}
|
|
1247
1523
|
async load({ tableName, keys }) {
|
|
@@ -1265,8 +1541,17 @@ var PostgresStore = class extends MastraStorage {
|
|
|
1265
1541
|
}
|
|
1266
1542
|
return result;
|
|
1267
1543
|
} catch (error) {
|
|
1268
|
-
|
|
1269
|
-
|
|
1544
|
+
throw new MastraError(
|
|
1545
|
+
{
|
|
1546
|
+
id: "MASTRA_STORAGE_PG_STORE_LOAD_FAILED",
|
|
1547
|
+
domain: ErrorDomain.STORAGE,
|
|
1548
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1549
|
+
details: {
|
|
1550
|
+
tableName
|
|
1551
|
+
}
|
|
1552
|
+
},
|
|
1553
|
+
error
|
|
1554
|
+
);
|
|
1270
1555
|
}
|
|
1271
1556
|
}
|
|
1272
1557
|
async getThreadById({ threadId }) {
|
|
@@ -1293,8 +1578,17 @@ var PostgresStore = class extends MastraStorage {
|
|
|
1293
1578
|
updatedAt: thread.updatedAt
|
|
1294
1579
|
};
|
|
1295
1580
|
} catch (error) {
|
|
1296
|
-
|
|
1297
|
-
|
|
1581
|
+
throw new MastraError(
|
|
1582
|
+
{
|
|
1583
|
+
id: "MASTRA_STORAGE_PG_STORE_GET_THREAD_BY_ID_FAILED",
|
|
1584
|
+
domain: ErrorDomain.STORAGE,
|
|
1585
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1586
|
+
details: {
|
|
1587
|
+
threadId
|
|
1588
|
+
}
|
|
1589
|
+
},
|
|
1590
|
+
error
|
|
1591
|
+
);
|
|
1298
1592
|
}
|
|
1299
1593
|
}
|
|
1300
1594
|
/**
|
|
@@ -1354,7 +1648,20 @@ var PostgresStore = class extends MastraStorage {
|
|
|
1354
1648
|
hasMore: currentOffset + threads.length < total
|
|
1355
1649
|
};
|
|
1356
1650
|
} catch (error) {
|
|
1357
|
-
|
|
1651
|
+
const mastraError = new MastraError(
|
|
1652
|
+
{
|
|
1653
|
+
id: "MASTRA_STORAGE_PG_STORE_GET_THREADS_BY_RESOURCE_ID_PAGINATED_FAILED",
|
|
1654
|
+
domain: ErrorDomain.STORAGE,
|
|
1655
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1656
|
+
details: {
|
|
1657
|
+
resourceId,
|
|
1658
|
+
page
|
|
1659
|
+
}
|
|
1660
|
+
},
|
|
1661
|
+
error
|
|
1662
|
+
);
|
|
1663
|
+
this.logger?.error?.(mastraError.toString());
|
|
1664
|
+
this.logger?.trackException(mastraError);
|
|
1358
1665
|
return { threads: [], total: 0, page, perPage: perPageInput || 100, hasMore: false };
|
|
1359
1666
|
}
|
|
1360
1667
|
}
|
|
@@ -1386,8 +1693,17 @@ var PostgresStore = class extends MastraStorage {
|
|
|
1386
1693
|
);
|
|
1387
1694
|
return thread;
|
|
1388
1695
|
} catch (error) {
|
|
1389
|
-
|
|
1390
|
-
|
|
1696
|
+
throw new MastraError(
|
|
1697
|
+
{
|
|
1698
|
+
id: "MASTRA_STORAGE_PG_STORE_SAVE_THREAD_FAILED",
|
|
1699
|
+
domain: ErrorDomain.STORAGE,
|
|
1700
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1701
|
+
details: {
|
|
1702
|
+
threadId: thread.id
|
|
1703
|
+
}
|
|
1704
|
+
},
|
|
1705
|
+
error
|
|
1706
|
+
);
|
|
1391
1707
|
}
|
|
1392
1708
|
}
|
|
1393
1709
|
async updateThread({
|
|
@@ -1395,20 +1711,29 @@ var PostgresStore = class extends MastraStorage {
|
|
|
1395
1711
|
title,
|
|
1396
1712
|
metadata
|
|
1397
1713
|
}) {
|
|
1714
|
+
const existingThread = await this.getThreadById({ threadId: id });
|
|
1715
|
+
if (!existingThread) {
|
|
1716
|
+
throw new MastraError({
|
|
1717
|
+
id: "MASTRA_STORAGE_PG_STORE_UPDATE_THREAD_FAILED",
|
|
1718
|
+
domain: ErrorDomain.STORAGE,
|
|
1719
|
+
category: ErrorCategory.USER,
|
|
1720
|
+
text: `Thread ${id} not found`,
|
|
1721
|
+
details: {
|
|
1722
|
+
threadId: id,
|
|
1723
|
+
title
|
|
1724
|
+
}
|
|
1725
|
+
});
|
|
1726
|
+
}
|
|
1727
|
+
const mergedMetadata = {
|
|
1728
|
+
...existingThread.metadata,
|
|
1729
|
+
...metadata
|
|
1730
|
+
};
|
|
1398
1731
|
try {
|
|
1399
|
-
const existingThread = await this.getThreadById({ threadId: id });
|
|
1400
|
-
if (!existingThread) {
|
|
1401
|
-
throw new Error(`Thread ${id} not found`);
|
|
1402
|
-
}
|
|
1403
|
-
const mergedMetadata = {
|
|
1404
|
-
...existingThread.metadata,
|
|
1405
|
-
...metadata
|
|
1406
|
-
};
|
|
1407
1732
|
const thread = await this.db.one(
|
|
1408
1733
|
`UPDATE ${this.getTableName(TABLE_THREADS)}
|
|
1409
1734
|
SET title = $1,
|
|
1410
|
-
|
|
1411
|
-
|
|
1735
|
+
metadata = $2,
|
|
1736
|
+
"updatedAt" = $3
|
|
1412
1737
|
WHERE id = $4
|
|
1413
1738
|
RETURNING *`,
|
|
1414
1739
|
[title, mergedMetadata, (/* @__PURE__ */ new Date()).toISOString(), id]
|
|
@@ -1420,8 +1745,18 @@ var PostgresStore = class extends MastraStorage {
|
|
|
1420
1745
|
updatedAt: thread.updatedAt
|
|
1421
1746
|
};
|
|
1422
1747
|
} catch (error) {
|
|
1423
|
-
|
|
1424
|
-
|
|
1748
|
+
throw new MastraError(
|
|
1749
|
+
{
|
|
1750
|
+
id: "MASTRA_STORAGE_PG_STORE_UPDATE_THREAD_FAILED",
|
|
1751
|
+
domain: ErrorDomain.STORAGE,
|
|
1752
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1753
|
+
details: {
|
|
1754
|
+
threadId: id,
|
|
1755
|
+
title
|
|
1756
|
+
}
|
|
1757
|
+
},
|
|
1758
|
+
error
|
|
1759
|
+
);
|
|
1425
1760
|
}
|
|
1426
1761
|
}
|
|
1427
1762
|
async deleteThread({ threadId }) {
|
|
@@ -1431,26 +1766,34 @@ var PostgresStore = class extends MastraStorage {
|
|
|
1431
1766
|
await t.none(`DELETE FROM ${this.getTableName(TABLE_THREADS)} WHERE id = $1`, [threadId]);
|
|
1432
1767
|
});
|
|
1433
1768
|
} catch (error) {
|
|
1434
|
-
|
|
1435
|
-
|
|
1769
|
+
throw new MastraError(
|
|
1770
|
+
{
|
|
1771
|
+
id: "MASTRA_STORAGE_PG_STORE_DELETE_THREAD_FAILED",
|
|
1772
|
+
domain: ErrorDomain.STORAGE,
|
|
1773
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1774
|
+
details: {
|
|
1775
|
+
threadId
|
|
1776
|
+
}
|
|
1777
|
+
},
|
|
1778
|
+
error
|
|
1779
|
+
);
|
|
1436
1780
|
}
|
|
1437
1781
|
}
|
|
1438
|
-
async
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
`
|
|
1782
|
+
async _getIncludedMessages({
|
|
1783
|
+
threadId,
|
|
1784
|
+
selectBy,
|
|
1785
|
+
orderByStatement
|
|
1786
|
+
}) {
|
|
1787
|
+
const include = selectBy?.include;
|
|
1788
|
+
if (!include) return null;
|
|
1789
|
+
const unionQueries = [];
|
|
1790
|
+
const params = [];
|
|
1791
|
+
let paramIdx = 1;
|
|
1792
|
+
for (const inc of include) {
|
|
1793
|
+
const { id, withPreviousMessages = 0, withNextMessages = 0 } = inc;
|
|
1794
|
+
const searchId = inc.threadId || threadId;
|
|
1795
|
+
unionQueries.push(
|
|
1796
|
+
`
|
|
1454
1797
|
SELECT * FROM (
|
|
1455
1798
|
WITH ordered_messages AS (
|
|
1456
1799
|
SELECT
|
|
@@ -1482,34 +1825,45 @@ var PostgresStore = class extends MastraStorage {
|
|
|
1482
1825
|
)
|
|
1483
1826
|
) AS query_${paramIdx}
|
|
1484
1827
|
`
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1828
|
+
// Keep ASC for final sorting after fetching context
|
|
1829
|
+
);
|
|
1830
|
+
params.push(searchId, id, withPreviousMessages, withNextMessages);
|
|
1831
|
+
paramIdx += 4;
|
|
1832
|
+
}
|
|
1833
|
+
const finalQuery = unionQueries.join(" UNION ALL ") + ' ORDER BY "createdAt" ASC';
|
|
1834
|
+
const includedRows = await this.db.manyOrNone(finalQuery, params);
|
|
1835
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1836
|
+
const dedupedRows = includedRows.filter((row) => {
|
|
1837
|
+
if (seen.has(row.id)) return false;
|
|
1838
|
+
seen.add(row.id);
|
|
1839
|
+
return true;
|
|
1840
|
+
});
|
|
1841
|
+
return dedupedRows;
|
|
1842
|
+
}
|
|
1843
|
+
async getMessages(args) {
|
|
1844
|
+
const { threadId, format, selectBy } = args;
|
|
1845
|
+
const selectStatement = `SELECT id, content, role, type, "createdAt", thread_id AS "threadId"`;
|
|
1846
|
+
const orderByStatement = `ORDER BY "createdAt" DESC`;
|
|
1847
|
+
const limit = this.resolveMessageLimit({ last: selectBy?.last, defaultLimit: 40 });
|
|
1848
|
+
try {
|
|
1849
|
+
let rows = [];
|
|
1850
|
+
const include = selectBy?.include || [];
|
|
1851
|
+
if (include?.length) {
|
|
1852
|
+
const includeMessages = await this._getIncludedMessages({ threadId, selectBy, orderByStatement });
|
|
1853
|
+
if (includeMessages) {
|
|
1854
|
+
rows.push(...includeMessages);
|
|
1511
1855
|
}
|
|
1512
1856
|
}
|
|
1857
|
+
const excludeIds = rows.map((m) => m.id);
|
|
1858
|
+
const excludeIdsParam = excludeIds.map((_, idx) => `$${idx + 2}`).join(", ");
|
|
1859
|
+
let query = `${selectStatement} FROM ${this.getTableName(TABLE_MESSAGES)} WHERE thread_id = $1
|
|
1860
|
+
${excludeIds.length ? `AND id NOT IN (${excludeIdsParam})` : ""}
|
|
1861
|
+
${orderByStatement}
|
|
1862
|
+
LIMIT $${excludeIds.length + 2}
|
|
1863
|
+
`;
|
|
1864
|
+
const queryParams = [threadId, ...excludeIds, limit];
|
|
1865
|
+
const remainingRows = await this.db.manyOrNone(query, queryParams);
|
|
1866
|
+
rows.push(...remainingRows);
|
|
1513
1867
|
const fetchedMessages = (rows || []).map((message) => {
|
|
1514
1868
|
if (typeof message.content === "string") {
|
|
1515
1869
|
try {
|
|
@@ -1527,7 +1881,19 @@ var PostgresStore = class extends MastraStorage {
|
|
|
1527
1881
|
(m) => ({ ...m, content: m.content || { format: 2, parts: [{ type: "text", text: "" }] } })
|
|
1528
1882
|
) : sortedMessages;
|
|
1529
1883
|
} catch (error) {
|
|
1530
|
-
|
|
1884
|
+
const mastraError = new MastraError(
|
|
1885
|
+
{
|
|
1886
|
+
id: "MASTRA_STORAGE_PG_STORE_GET_MESSAGES_FAILED",
|
|
1887
|
+
domain: ErrorDomain.STORAGE,
|
|
1888
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1889
|
+
details: {
|
|
1890
|
+
threadId
|
|
1891
|
+
}
|
|
1892
|
+
},
|
|
1893
|
+
error
|
|
1894
|
+
);
|
|
1895
|
+
this.logger?.error?.(mastraError.toString());
|
|
1896
|
+
this.logger?.trackException(mastraError);
|
|
1531
1897
|
return [];
|
|
1532
1898
|
}
|
|
1533
1899
|
}
|
|
@@ -1538,8 +1904,15 @@ var PostgresStore = class extends MastraStorage {
|
|
|
1538
1904
|
const toDate = dateRange?.end;
|
|
1539
1905
|
const selectStatement = `SELECT id, content, role, type, "createdAt", thread_id AS "threadId"`;
|
|
1540
1906
|
const orderByStatement = `ORDER BY "createdAt" DESC`;
|
|
1907
|
+
const messages = [];
|
|
1908
|
+
if (selectBy?.include?.length) {
|
|
1909
|
+
const includeMessages = await this._getIncludedMessages({ threadId, selectBy, orderByStatement });
|
|
1910
|
+
if (includeMessages) {
|
|
1911
|
+
messages.push(...includeMessages);
|
|
1912
|
+
}
|
|
1913
|
+
}
|
|
1541
1914
|
try {
|
|
1542
|
-
const perPage = perPageInput !== void 0 ? perPageInput : 40;
|
|
1915
|
+
const perPage = perPageInput !== void 0 ? perPageInput : this.resolveMessageLimit({ last: selectBy?.last, defaultLimit: 40 });
|
|
1543
1916
|
const currentOffset = page * perPage;
|
|
1544
1917
|
const conditions = [`thread_id = $1`];
|
|
1545
1918
|
const queryParams = [threadId];
|
|
@@ -1556,7 +1929,7 @@ var PostgresStore = class extends MastraStorage {
|
|
|
1556
1929
|
const countQuery = `SELECT COUNT(*) FROM ${this.getTableName(TABLE_MESSAGES)} ${whereClause}`;
|
|
1557
1930
|
const countResult = await this.db.one(countQuery, queryParams);
|
|
1558
1931
|
const total = parseInt(countResult.count, 10);
|
|
1559
|
-
if (total === 0) {
|
|
1932
|
+
if (total === 0 && messages.length === 0) {
|
|
1560
1933
|
return {
|
|
1561
1934
|
messages: [],
|
|
1562
1935
|
total: 0,
|
|
@@ -1565,11 +1938,15 @@ var PostgresStore = class extends MastraStorage {
|
|
|
1565
1938
|
hasMore: false
|
|
1566
1939
|
};
|
|
1567
1940
|
}
|
|
1941
|
+
const excludeIds = messages.map((m) => m.id);
|
|
1942
|
+
const excludeIdsParam = excludeIds.map((_, idx) => `$${idx + paramIndex}`).join(", ");
|
|
1943
|
+
paramIndex += excludeIds.length;
|
|
1568
1944
|
const dataQuery = `${selectStatement} FROM ${this.getTableName(
|
|
1569
1945
|
TABLE_MESSAGES
|
|
1570
|
-
)} ${whereClause} ${orderByStatement} LIMIT $${paramIndex++} OFFSET $${paramIndex++}`;
|
|
1571
|
-
const rows = await this.db.manyOrNone(dataQuery, [...queryParams, perPage, currentOffset]);
|
|
1572
|
-
|
|
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]);
|
|
1948
|
+
messages.push(...rows || []);
|
|
1949
|
+
const list = new MessageList().add(messages, "memory");
|
|
1573
1950
|
const messagesToReturn = format === `v2` ? list.get.all.v2() : list.get.all.v1();
|
|
1574
1951
|
return {
|
|
1575
1952
|
messages: messagesToReturn,
|
|
@@ -1579,7 +1956,20 @@ var PostgresStore = class extends MastraStorage {
|
|
|
1579
1956
|
hasMore: currentOffset + rows.length < total
|
|
1580
1957
|
};
|
|
1581
1958
|
} catch (error) {
|
|
1582
|
-
|
|
1959
|
+
const mastraError = new MastraError(
|
|
1960
|
+
{
|
|
1961
|
+
id: "MASTRA_STORAGE_PG_STORE_GET_MESSAGES_PAGINATED_FAILED",
|
|
1962
|
+
domain: ErrorDomain.STORAGE,
|
|
1963
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1964
|
+
details: {
|
|
1965
|
+
threadId,
|
|
1966
|
+
page
|
|
1967
|
+
}
|
|
1968
|
+
},
|
|
1969
|
+
error
|
|
1970
|
+
);
|
|
1971
|
+
this.logger?.error?.(mastraError.toString());
|
|
1972
|
+
this.logger?.trackException(mastraError);
|
|
1583
1973
|
return { messages: [], total: 0, page, perPage: perPageInput || 40, hasMore: false };
|
|
1584
1974
|
}
|
|
1585
1975
|
}
|
|
@@ -1588,15 +1978,28 @@ var PostgresStore = class extends MastraStorage {
|
|
|
1588
1978
|
format
|
|
1589
1979
|
}) {
|
|
1590
1980
|
if (messages.length === 0) return messages;
|
|
1981
|
+
const threadId = messages[0]?.threadId;
|
|
1982
|
+
if (!threadId) {
|
|
1983
|
+
throw new MastraError({
|
|
1984
|
+
id: "MASTRA_STORAGE_PG_STORE_SAVE_MESSAGES_FAILED",
|
|
1985
|
+
domain: ErrorDomain.STORAGE,
|
|
1986
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1987
|
+
text: `Thread ID is required`
|
|
1988
|
+
});
|
|
1989
|
+
}
|
|
1990
|
+
const thread = await this.getThreadById({ threadId });
|
|
1991
|
+
if (!thread) {
|
|
1992
|
+
throw new MastraError({
|
|
1993
|
+
id: "MASTRA_STORAGE_PG_STORE_SAVE_MESSAGES_FAILED",
|
|
1994
|
+
domain: ErrorDomain.STORAGE,
|
|
1995
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1996
|
+
text: `Thread ${threadId} not found`,
|
|
1997
|
+
details: {
|
|
1998
|
+
threadId
|
|
1999
|
+
}
|
|
2000
|
+
});
|
|
2001
|
+
}
|
|
1591
2002
|
try {
|
|
1592
|
-
const threadId = messages[0]?.threadId;
|
|
1593
|
-
if (!threadId) {
|
|
1594
|
-
throw new Error("Thread ID is required");
|
|
1595
|
-
}
|
|
1596
|
-
const thread = await this.getThreadById({ threadId });
|
|
1597
|
-
if (!thread) {
|
|
1598
|
-
throw new Error(`Thread ${threadId} not found`);
|
|
1599
|
-
}
|
|
1600
2003
|
await this.db.tx(async (t) => {
|
|
1601
2004
|
const messageInserts = messages.map((message) => {
|
|
1602
2005
|
if (!message.threadId) {
|
|
@@ -1611,7 +2014,13 @@ var PostgresStore = class extends MastraStorage {
|
|
|
1611
2014
|
}
|
|
1612
2015
|
return t.none(
|
|
1613
2016
|
`INSERT INTO ${this.getTableName(TABLE_MESSAGES)} (id, thread_id, content, "createdAt", role, type, "resourceId")
|
|
1614
|
-
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"`,
|
|
1615
2024
|
[
|
|
1616
2025
|
message.id,
|
|
1617
2026
|
message.threadId,
|
|
@@ -1635,8 +2044,17 @@ var PostgresStore = class extends MastraStorage {
|
|
|
1635
2044
|
if (format === `v2`) return list.get.all.v2();
|
|
1636
2045
|
return list.get.all.v1();
|
|
1637
2046
|
} catch (error) {
|
|
1638
|
-
|
|
1639
|
-
|
|
2047
|
+
throw new MastraError(
|
|
2048
|
+
{
|
|
2049
|
+
id: "MASTRA_STORAGE_PG_STORE_SAVE_MESSAGES_FAILED",
|
|
2050
|
+
domain: ErrorDomain.STORAGE,
|
|
2051
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
2052
|
+
details: {
|
|
2053
|
+
threadId
|
|
2054
|
+
}
|
|
2055
|
+
},
|
|
2056
|
+
error
|
|
2057
|
+
);
|
|
1640
2058
|
}
|
|
1641
2059
|
}
|
|
1642
2060
|
async persistWorkflowSnapshot({
|
|
@@ -1660,8 +2078,18 @@ var PostgresStore = class extends MastraStorage {
|
|
|
1660
2078
|
[workflowName, runId, JSON.stringify(snapshot), now, now]
|
|
1661
2079
|
);
|
|
1662
2080
|
} catch (error) {
|
|
1663
|
-
|
|
1664
|
-
|
|
2081
|
+
throw new MastraError(
|
|
2082
|
+
{
|
|
2083
|
+
id: "MASTRA_STORAGE_PG_STORE_PERSIST_WORKFLOW_SNAPSHOT_FAILED",
|
|
2084
|
+
domain: ErrorDomain.STORAGE,
|
|
2085
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
2086
|
+
details: {
|
|
2087
|
+
workflowName,
|
|
2088
|
+
runId
|
|
2089
|
+
}
|
|
2090
|
+
},
|
|
2091
|
+
error
|
|
2092
|
+
);
|
|
1665
2093
|
}
|
|
1666
2094
|
}
|
|
1667
2095
|
async loadWorkflowSnapshot({
|
|
@@ -1681,8 +2109,18 @@ var PostgresStore = class extends MastraStorage {
|
|
|
1681
2109
|
}
|
|
1682
2110
|
return result.snapshot;
|
|
1683
2111
|
} catch (error) {
|
|
1684
|
-
|
|
1685
|
-
|
|
2112
|
+
throw new MastraError(
|
|
2113
|
+
{
|
|
2114
|
+
id: "MASTRA_STORAGE_PG_STORE_LOAD_WORKFLOW_SNAPSHOT_FAILED",
|
|
2115
|
+
domain: ErrorDomain.STORAGE,
|
|
2116
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
2117
|
+
details: {
|
|
2118
|
+
workflowName,
|
|
2119
|
+
runId
|
|
2120
|
+
}
|
|
2121
|
+
},
|
|
2122
|
+
error
|
|
2123
|
+
);
|
|
1686
2124
|
}
|
|
1687
2125
|
}
|
|
1688
2126
|
async hasColumn(table, column) {
|
|
@@ -1770,8 +2208,17 @@ var PostgresStore = class extends MastraStorage {
|
|
|
1770
2208
|
});
|
|
1771
2209
|
return { runs, total: total || runs.length };
|
|
1772
2210
|
} catch (error) {
|
|
1773
|
-
|
|
1774
|
-
|
|
2211
|
+
throw new MastraError(
|
|
2212
|
+
{
|
|
2213
|
+
id: "MASTRA_STORAGE_PG_STORE_GET_WORKFLOW_RUNS_FAILED",
|
|
2214
|
+
domain: ErrorDomain.STORAGE,
|
|
2215
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
2216
|
+
details: {
|
|
2217
|
+
workflowName: workflowName || "all"
|
|
2218
|
+
}
|
|
2219
|
+
},
|
|
2220
|
+
error
|
|
2221
|
+
);
|
|
1775
2222
|
}
|
|
1776
2223
|
}
|
|
1777
2224
|
async getWorkflowRunById({
|
|
@@ -1804,8 +2251,18 @@ var PostgresStore = class extends MastraStorage {
|
|
|
1804
2251
|
}
|
|
1805
2252
|
return this.parseWorkflowRun(result);
|
|
1806
2253
|
} catch (error) {
|
|
1807
|
-
|
|
1808
|
-
|
|
2254
|
+
throw new MastraError(
|
|
2255
|
+
{
|
|
2256
|
+
id: "MASTRA_STORAGE_PG_STORE_GET_WORKFLOW_RUN_BY_ID_FAILED",
|
|
2257
|
+
domain: ErrorDomain.STORAGE,
|
|
2258
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
2259
|
+
details: {
|
|
2260
|
+
runId,
|
|
2261
|
+
workflowName: workflowName || ""
|
|
2262
|
+
}
|
|
2263
|
+
},
|
|
2264
|
+
error
|
|
2265
|
+
);
|
|
1809
2266
|
}
|
|
1810
2267
|
}
|
|
1811
2268
|
async close() {
|
|
@@ -1837,29 +2294,49 @@ var PostgresStore = class extends MastraStorage {
|
|
|
1837
2294
|
}
|
|
1838
2295
|
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
1839
2296
|
const countQuery = `SELECT COUNT(*) FROM ${this.getTableName(TABLE_EVALS)} ${whereClause}`;
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
2297
|
+
try {
|
|
2298
|
+
const countResult = await this.db.one(countQuery, queryParams);
|
|
2299
|
+
const total = parseInt(countResult.count, 10);
|
|
2300
|
+
const currentOffset = page * perPage;
|
|
2301
|
+
if (total === 0) {
|
|
2302
|
+
return {
|
|
2303
|
+
evals: [],
|
|
2304
|
+
total: 0,
|
|
2305
|
+
page,
|
|
2306
|
+
perPage,
|
|
2307
|
+
hasMore: false
|
|
2308
|
+
};
|
|
2309
|
+
}
|
|
2310
|
+
const dataQuery = `SELECT * FROM ${this.getTableName(
|
|
2311
|
+
TABLE_EVALS
|
|
2312
|
+
)} ${whereClause} ORDER BY created_at DESC LIMIT $${paramIndex++} OFFSET $${paramIndex++}`;
|
|
2313
|
+
const rows = await this.db.manyOrNone(dataQuery, [...queryParams, perPage, currentOffset]);
|
|
1844
2314
|
return {
|
|
1845
|
-
evals: [],
|
|
1846
|
-
total
|
|
2315
|
+
evals: rows?.map((row) => this.transformEvalRow(row)) ?? [],
|
|
2316
|
+
total,
|
|
1847
2317
|
page,
|
|
1848
2318
|
perPage,
|
|
1849
|
-
hasMore:
|
|
2319
|
+
hasMore: currentOffset + (rows?.length ?? 0) < total
|
|
1850
2320
|
};
|
|
2321
|
+
} catch (error) {
|
|
2322
|
+
const mastraError = new MastraError(
|
|
2323
|
+
{
|
|
2324
|
+
id: "MASTRA_STORAGE_PG_STORE_GET_EVALS_FAILED",
|
|
2325
|
+
domain: ErrorDomain.STORAGE,
|
|
2326
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
2327
|
+
details: {
|
|
2328
|
+
agentName: agentName || "all",
|
|
2329
|
+
type: type || "all",
|
|
2330
|
+
page,
|
|
2331
|
+
perPage
|
|
2332
|
+
}
|
|
2333
|
+
},
|
|
2334
|
+
error
|
|
2335
|
+
);
|
|
2336
|
+
this.logger?.error?.(mastraError.toString());
|
|
2337
|
+
this.logger?.trackException(mastraError);
|
|
2338
|
+
throw mastraError;
|
|
1851
2339
|
}
|
|
1852
|
-
const dataQuery = `SELECT * FROM ${this.getTableName(
|
|
1853
|
-
TABLE_EVALS
|
|
1854
|
-
)} ${whereClause} ORDER BY created_at DESC LIMIT $${paramIndex++} OFFSET $${paramIndex++}`;
|
|
1855
|
-
const rows = await this.db.manyOrNone(dataQuery, [...queryParams, perPage, currentOffset]);
|
|
1856
|
-
return {
|
|
1857
|
-
evals: rows?.map((row) => this.transformEvalRow(row)) ?? [],
|
|
1858
|
-
total,
|
|
1859
|
-
page,
|
|
1860
|
-
perPage,
|
|
1861
|
-
hasMore: currentOffset + (rows?.length ?? 0) < total
|
|
1862
|
-
};
|
|
1863
2340
|
}
|
|
1864
2341
|
async updateMessages({
|
|
1865
2342
|
messages
|
|
@@ -1956,6 +2433,82 @@ var PostgresStore = class extends MastraStorage {
|
|
|
1956
2433
|
return message;
|
|
1957
2434
|
});
|
|
1958
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
|
+
}
|
|
1959
2512
|
};
|
|
1960
2513
|
|
|
1961
2514
|
// src/vector/prompt.ts
|