@mastra/pg 1.0.0-beta.5 → 1.0.0-beta.7
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 +76 -0
- package/dist/index.cjs +440 -32
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +441 -33
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/agents/index.d.ts +25 -0
- package/dist/storage/domains/agents/index.d.ts.map +1 -0
- package/dist/storage/domains/workflows/index.d.ts +4 -0
- package/dist/storage/domains/workflows/index.d.ts.map +1 -1
- package/dist/storage/index.d.ts +5 -0
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/vector/index.d.ts +31 -3
- package/dist/vector/index.d.ts.map +1 -1
- package/dist/vector/types.d.ts +10 -0
- package/dist/vector/types.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { MastraError, ErrorCategory, ErrorDomain } from '@mastra/core/error';
|
|
2
|
-
import { createVectorErrorId, MastraStorage, createStorageErrorId, StoreOperations, TABLE_SCHEMAS, TABLE_WORKFLOW_SNAPSHOT, TABLE_SPANS, TABLE_THREADS, TABLE_MESSAGES, TABLE_TRACES, TABLE_SCORERS, ScoresStorage, normalizePerPage, calculatePagination, WorkflowsStorage, MemoryStorage, TABLE_RESOURCES, ObservabilityStorage, transformScoreRow as transformScoreRow$1 } from '@mastra/core/storage';
|
|
2
|
+
import { createVectorErrorId, MastraStorage, createStorageErrorId, StoreOperations, TABLE_SCHEMAS, TABLE_WORKFLOW_SNAPSHOT, TABLE_SPANS, TABLE_THREADS, TABLE_MESSAGES, TABLE_TRACES, TABLE_SCORERS, ScoresStorage, normalizePerPage, calculatePagination, WorkflowsStorage, MemoryStorage, TABLE_RESOURCES, ObservabilityStorage, AgentsStorage, transformScoreRow as transformScoreRow$1, TABLE_AGENTS } from '@mastra/core/storage';
|
|
3
3
|
import { parseSqlIdentifier, parseFieldKey } from '@mastra/core/utils';
|
|
4
4
|
import { MastraVector } from '@mastra/core/vector';
|
|
5
5
|
import { Mutex } from 'async-mutex';
|
|
@@ -480,12 +480,14 @@ var PgVector = class extends MastraVector {
|
|
|
480
480
|
pool;
|
|
481
481
|
describeIndexCache = /* @__PURE__ */ new Map();
|
|
482
482
|
createdIndexes = /* @__PURE__ */ new Map();
|
|
483
|
+
indexVectorTypes = /* @__PURE__ */ new Map();
|
|
483
484
|
mutexesByName = /* @__PURE__ */ new Map();
|
|
484
485
|
schema;
|
|
485
486
|
setupSchemaPromise = null;
|
|
486
487
|
installVectorExtensionPromise = null;
|
|
487
488
|
vectorExtensionInstalled = void 0;
|
|
488
489
|
vectorExtensionSchema = null;
|
|
490
|
+
vectorExtensionVersion = null;
|
|
489
491
|
schemaSetupComplete = void 0;
|
|
490
492
|
cacheWarmupPromise = null;
|
|
491
493
|
constructor(config) {
|
|
@@ -538,9 +540,11 @@ var PgVector = class extends MastraVector {
|
|
|
538
540
|
indexName,
|
|
539
541
|
metric: info.metric,
|
|
540
542
|
dimension: info.dimension,
|
|
541
|
-
type: info.type
|
|
543
|
+
type: info.type,
|
|
544
|
+
vectorType: info.vectorType
|
|
542
545
|
});
|
|
543
546
|
this.createdIndexes.set(indexName, key);
|
|
547
|
+
this.indexVectorTypes.set(indexName, info.vectorType);
|
|
544
548
|
})
|
|
545
549
|
);
|
|
546
550
|
} catch (error) {
|
|
@@ -566,12 +570,12 @@ var PgVector = class extends MastraVector {
|
|
|
566
570
|
return this.mutexesByName.get(indexName);
|
|
567
571
|
}
|
|
568
572
|
/**
|
|
569
|
-
* Detects which schema contains the vector extension
|
|
573
|
+
* Detects which schema contains the vector extension and its version
|
|
570
574
|
*/
|
|
571
575
|
async detectVectorExtensionSchema(client) {
|
|
572
576
|
try {
|
|
573
577
|
const result = await client.query(`
|
|
574
|
-
SELECT n.nspname as schema_name
|
|
578
|
+
SELECT n.nspname as schema_name, e.extversion as version
|
|
575
579
|
FROM pg_extension e
|
|
576
580
|
JOIN pg_namespace n ON e.extnamespace = n.oid
|
|
577
581
|
WHERE e.extname = 'vector'
|
|
@@ -579,7 +583,11 @@ var PgVector = class extends MastraVector {
|
|
|
579
583
|
`);
|
|
580
584
|
if (result.rows.length > 0) {
|
|
581
585
|
this.vectorExtensionSchema = result.rows[0].schema_name;
|
|
582
|
-
this.
|
|
586
|
+
this.vectorExtensionVersion = result.rows[0].version;
|
|
587
|
+
this.logger.debug("Vector extension found", {
|
|
588
|
+
schema: this.vectorExtensionSchema,
|
|
589
|
+
version: this.vectorExtensionVersion
|
|
590
|
+
});
|
|
583
591
|
return this.vectorExtensionSchema;
|
|
584
592
|
}
|
|
585
593
|
return null;
|
|
@@ -588,18 +596,52 @@ var PgVector = class extends MastraVector {
|
|
|
588
596
|
return null;
|
|
589
597
|
}
|
|
590
598
|
}
|
|
599
|
+
/**
|
|
600
|
+
* Checks if the installed pgvector version supports halfvec type.
|
|
601
|
+
* halfvec was introduced in pgvector 0.7.0.
|
|
602
|
+
*/
|
|
603
|
+
supportsHalfvec() {
|
|
604
|
+
if (!this.vectorExtensionVersion) {
|
|
605
|
+
return false;
|
|
606
|
+
}
|
|
607
|
+
const parts = this.vectorExtensionVersion.split(".");
|
|
608
|
+
const major = parseInt(parts[0] ?? "", 10);
|
|
609
|
+
const minor = parseInt(parts[1] ?? "", 10);
|
|
610
|
+
if (isNaN(major) || isNaN(minor)) {
|
|
611
|
+
return false;
|
|
612
|
+
}
|
|
613
|
+
return major > 0 || major === 0 && minor >= 7;
|
|
614
|
+
}
|
|
591
615
|
/**
|
|
592
616
|
* Gets the properly qualified vector type name
|
|
617
|
+
* @param vectorType - The type of vector storage ('vector' or 'halfvec')
|
|
593
618
|
*/
|
|
594
|
-
getVectorTypeName() {
|
|
619
|
+
getVectorTypeName(vectorType = "vector") {
|
|
595
620
|
if (this.vectorExtensionSchema) {
|
|
596
621
|
if (this.vectorExtensionSchema === "pg_catalog") {
|
|
597
|
-
return
|
|
622
|
+
return vectorType;
|
|
598
623
|
}
|
|
599
624
|
const validatedSchema = parseSqlIdentifier(this.vectorExtensionSchema, "vector extension schema");
|
|
600
|
-
return `${validatedSchema}
|
|
625
|
+
return `${validatedSchema}.${vectorType}`;
|
|
626
|
+
}
|
|
627
|
+
return vectorType;
|
|
628
|
+
}
|
|
629
|
+
/**
|
|
630
|
+
* Gets the operator class for index creation based on metric and vector type.
|
|
631
|
+
* pgvector uses different operator classes for vector vs halfvec types.
|
|
632
|
+
*/
|
|
633
|
+
getMetricOperatorClass(metric, vectorType) {
|
|
634
|
+
const prefix = vectorType === "halfvec" ? "halfvec" : "vector";
|
|
635
|
+
switch (metric) {
|
|
636
|
+
case "cosine":
|
|
637
|
+
return `${prefix}_cosine_ops`;
|
|
638
|
+
case "euclidean":
|
|
639
|
+
return `${prefix}_l2_ops`;
|
|
640
|
+
case "dotproduct":
|
|
641
|
+
return `${prefix}_ip_ops`;
|
|
642
|
+
default:
|
|
643
|
+
return `${prefix}_cosine_ops`;
|
|
601
644
|
}
|
|
602
|
-
return "vector";
|
|
603
645
|
}
|
|
604
646
|
getTableName(indexName) {
|
|
605
647
|
const parsedIndexName = parseSqlIdentifier(indexName, "index name");
|
|
@@ -672,12 +714,12 @@ var PgVector = class extends MastraVector {
|
|
|
672
714
|
await client.query(`SET LOCAL ivfflat.probes = ${probes}`);
|
|
673
715
|
}
|
|
674
716
|
const { tableName } = this.getTableName(indexName);
|
|
675
|
-
const
|
|
717
|
+
const qualifiedVectorType = this.getVectorTypeName(indexInfo.vectorType);
|
|
676
718
|
const query = `
|
|
677
719
|
WITH vector_scores AS (
|
|
678
720
|
SELECT
|
|
679
721
|
vector_id as id,
|
|
680
|
-
1 - (embedding <=> '${vectorStr}'::${
|
|
722
|
+
1 - (embedding <=> '${vectorStr}'::${qualifiedVectorType}) as score,
|
|
681
723
|
metadata
|
|
682
724
|
${includeVector ? ", embedding" : ""}
|
|
683
725
|
FROM ${tableName}
|
|
@@ -741,14 +783,15 @@ var PgVector = class extends MastraVector {
|
|
|
741
783
|
}
|
|
742
784
|
}
|
|
743
785
|
const vectorIds = ids || vectors.map(() => crypto.randomUUID());
|
|
744
|
-
const
|
|
786
|
+
const indexInfo = await this.getIndexInfo({ indexName });
|
|
787
|
+
const qualifiedVectorType = this.getVectorTypeName(indexInfo.vectorType);
|
|
745
788
|
for (let i = 0; i < vectors.length; i++) {
|
|
746
789
|
const query = `
|
|
747
790
|
INSERT INTO ${tableName} (vector_id, embedding, metadata)
|
|
748
|
-
VALUES ($1, $2::${
|
|
791
|
+
VALUES ($1, $2::${qualifiedVectorType}, $3::jsonb)
|
|
749
792
|
ON CONFLICT (vector_id)
|
|
750
793
|
DO UPDATE SET
|
|
751
|
-
embedding = $2::${
|
|
794
|
+
embedding = $2::${qualifiedVectorType},
|
|
752
795
|
metadata = $3::jsonb
|
|
753
796
|
RETURNING embedding::text
|
|
754
797
|
`;
|
|
@@ -807,9 +850,10 @@ var PgVector = class extends MastraVector {
|
|
|
807
850
|
indexName,
|
|
808
851
|
dimension,
|
|
809
852
|
metric,
|
|
810
|
-
type
|
|
853
|
+
type,
|
|
854
|
+
vectorType = "vector"
|
|
811
855
|
}) {
|
|
812
|
-
const input = indexName + dimension + metric + (type || "ivfflat");
|
|
856
|
+
const input = indexName + dimension + metric + (type || "ivfflat") + vectorType;
|
|
813
857
|
return (await this.hasher).h32(input);
|
|
814
858
|
}
|
|
815
859
|
cachedIndexExists(indexName, newKey) {
|
|
@@ -862,7 +906,8 @@ var PgVector = class extends MastraVector {
|
|
|
862
906
|
dimension,
|
|
863
907
|
metric = "cosine",
|
|
864
908
|
indexConfig = {},
|
|
865
|
-
buildIndex = true
|
|
909
|
+
buildIndex = true,
|
|
910
|
+
vectorType = "vector"
|
|
866
911
|
}) {
|
|
867
912
|
const { tableName } = this.getTableName(indexName);
|
|
868
913
|
try {
|
|
@@ -872,6 +917,9 @@ var PgVector = class extends MastraVector {
|
|
|
872
917
|
if (!Number.isInteger(dimension) || dimension <= 0) {
|
|
873
918
|
throw new Error("Dimension must be a positive integer");
|
|
874
919
|
}
|
|
920
|
+
if (vectorType !== "vector" && vectorType !== "halfvec") {
|
|
921
|
+
throw new Error('vectorType must be "vector" or "halfvec"');
|
|
922
|
+
}
|
|
875
923
|
} catch (error) {
|
|
876
924
|
const mastraError = new MastraError(
|
|
877
925
|
{
|
|
@@ -887,7 +935,13 @@ var PgVector = class extends MastraVector {
|
|
|
887
935
|
this.logger?.trackException(mastraError);
|
|
888
936
|
throw mastraError;
|
|
889
937
|
}
|
|
890
|
-
const indexCacheKey = await this.getIndexCacheKey({
|
|
938
|
+
const indexCacheKey = await this.getIndexCacheKey({
|
|
939
|
+
indexName,
|
|
940
|
+
dimension,
|
|
941
|
+
type: indexConfig.type,
|
|
942
|
+
metric,
|
|
943
|
+
vectorType
|
|
944
|
+
});
|
|
891
945
|
if (this.cachedIndexExists(indexName, indexCacheKey)) {
|
|
892
946
|
return;
|
|
893
947
|
}
|
|
@@ -900,24 +954,40 @@ var PgVector = class extends MastraVector {
|
|
|
900
954
|
try {
|
|
901
955
|
await this.setupSchema(client);
|
|
902
956
|
await this.installVectorExtension(client);
|
|
957
|
+
if (vectorType === "halfvec" && !this.supportsHalfvec()) {
|
|
958
|
+
throw new MastraError({
|
|
959
|
+
id: createVectorErrorId("PG", "CREATE_INDEX", "HALFVEC_NOT_SUPPORTED"),
|
|
960
|
+
text: `halfvec type requires pgvector >= 0.7.0, but version ${this.vectorExtensionVersion || "unknown"} is installed. Either upgrade pgvector or use vectorType: 'vector' (which supports up to 2000 dimensions for indexes).`,
|
|
961
|
+
domain: ErrorDomain.MASTRA_VECTOR,
|
|
962
|
+
category: ErrorCategory.USER,
|
|
963
|
+
details: {
|
|
964
|
+
indexName,
|
|
965
|
+
requestedVectorType: vectorType,
|
|
966
|
+
pgvectorVersion: this.vectorExtensionVersion || "unknown",
|
|
967
|
+
requiredVersion: "0.7.0"
|
|
968
|
+
}
|
|
969
|
+
});
|
|
970
|
+
}
|
|
903
971
|
if (this.schema && this.vectorExtensionSchema && this.schema !== this.vectorExtensionSchema && this.vectorExtensionSchema !== "pg_catalog") {
|
|
904
972
|
await client.query(`SET search_path TO ${this.getSchemaName()}, "${this.vectorExtensionSchema}"`);
|
|
905
973
|
}
|
|
906
|
-
const
|
|
974
|
+
const qualifiedVectorType = this.getVectorTypeName(vectorType);
|
|
907
975
|
await client.query(`
|
|
908
976
|
CREATE TABLE IF NOT EXISTS ${tableName} (
|
|
909
977
|
id SERIAL PRIMARY KEY,
|
|
910
978
|
vector_id TEXT UNIQUE NOT NULL,
|
|
911
|
-
embedding ${
|
|
979
|
+
embedding ${qualifiedVectorType}(${dimension}),
|
|
912
980
|
metadata JSONB DEFAULT '{}'::jsonb
|
|
913
981
|
);
|
|
914
982
|
`);
|
|
915
983
|
this.createdIndexes.set(indexName, indexCacheKey);
|
|
984
|
+
this.indexVectorTypes.set(indexName, vectorType);
|
|
916
985
|
if (buildIndex) {
|
|
917
|
-
await this.setupIndex({ indexName, metric, indexConfig }, client);
|
|
986
|
+
await this.setupIndex({ indexName, metric, indexConfig, vectorType }, client);
|
|
918
987
|
}
|
|
919
988
|
} catch (error) {
|
|
920
989
|
this.createdIndexes.delete(indexName);
|
|
990
|
+
this.indexVectorTypes.delete(indexName);
|
|
921
991
|
throw error;
|
|
922
992
|
} finally {
|
|
923
993
|
client.release();
|
|
@@ -960,7 +1030,7 @@ var PgVector = class extends MastraVector {
|
|
|
960
1030
|
client.release();
|
|
961
1031
|
}
|
|
962
1032
|
}
|
|
963
|
-
async setupIndex({ indexName, metric, indexConfig }, client) {
|
|
1033
|
+
async setupIndex({ indexName, metric, indexConfig, vectorType = "vector" }, client) {
|
|
964
1034
|
const mutex = this.getMutexByName(`build-${indexName}`);
|
|
965
1035
|
await mutex.runExclusive(async () => {
|
|
966
1036
|
const isConfigEmpty = !indexConfig || Object.keys(indexConfig).length === 0 || !indexConfig.type && !indexConfig.ivf && !indexConfig.hnsw;
|
|
@@ -982,9 +1052,11 @@ var PgVector = class extends MastraVector {
|
|
|
982
1052
|
indexName,
|
|
983
1053
|
dimension,
|
|
984
1054
|
type: existingIndexInfo.type,
|
|
985
|
-
metric: existingIndexInfo.metric
|
|
1055
|
+
metric: existingIndexInfo.metric,
|
|
1056
|
+
vectorType: existingIndexInfo.vectorType
|
|
986
1057
|
});
|
|
987
1058
|
this.createdIndexes.set(indexName, cacheKey);
|
|
1059
|
+
this.indexVectorTypes.set(indexName, existingIndexInfo.vectorType);
|
|
988
1060
|
return;
|
|
989
1061
|
}
|
|
990
1062
|
}
|
|
@@ -1002,9 +1074,11 @@ var PgVector = class extends MastraVector {
|
|
|
1002
1074
|
indexName,
|
|
1003
1075
|
dimension,
|
|
1004
1076
|
type: existingIndexInfo.type,
|
|
1005
|
-
metric: existingIndexInfo.metric
|
|
1077
|
+
metric: existingIndexInfo.metric,
|
|
1078
|
+
vectorType: existingIndexInfo.vectorType
|
|
1006
1079
|
});
|
|
1007
1080
|
this.createdIndexes.set(indexName, cacheKey);
|
|
1081
|
+
this.indexVectorTypes.set(indexName, existingIndexInfo.vectorType);
|
|
1008
1082
|
return;
|
|
1009
1083
|
}
|
|
1010
1084
|
this.logger?.info(`Index ${vectorIndexName} configuration changed, rebuilding index`);
|
|
@@ -1017,7 +1091,8 @@ var PgVector = class extends MastraVector {
|
|
|
1017
1091
|
this.describeIndexCache.delete(indexName);
|
|
1018
1092
|
return;
|
|
1019
1093
|
}
|
|
1020
|
-
const
|
|
1094
|
+
const effectiveVectorType = existingIndexInfo?.vectorType ?? vectorType;
|
|
1095
|
+
const metricOp = this.getMetricOperatorClass(metric, effectiveVectorType);
|
|
1021
1096
|
let indexSQL;
|
|
1022
1097
|
if (indexType === "hnsw") {
|
|
1023
1098
|
const m = indexConfig.hnsw?.m ?? 8;
|
|
@@ -1067,6 +1142,12 @@ var PgVector = class extends MastraVector {
|
|
|
1067
1142
|
if (this.schema && this.schema !== "public") {
|
|
1068
1143
|
try {
|
|
1069
1144
|
await client.query(`CREATE EXTENSION IF NOT EXISTS vector SCHEMA ${this.getSchemaName()}`);
|
|
1145
|
+
const installedSchema2 = await this.detectVectorExtensionSchema(client);
|
|
1146
|
+
if (installedSchema2) {
|
|
1147
|
+
this.vectorExtensionInstalled = true;
|
|
1148
|
+
this.logger.info(`Vector extension installed in schema: ${installedSchema2}`);
|
|
1149
|
+
return;
|
|
1150
|
+
}
|
|
1070
1151
|
this.vectorExtensionInstalled = true;
|
|
1071
1152
|
this.vectorExtensionSchema = this.schema;
|
|
1072
1153
|
this.logger.info(`Vector extension installed in schema: ${this.schema}`);
|
|
@@ -1129,7 +1210,7 @@ var PgVector = class extends MastraVector {
|
|
|
1129
1210
|
WHERE c.table_schema = t.table_schema
|
|
1130
1211
|
AND c.table_name = t.table_name
|
|
1131
1212
|
AND c.column_name = 'embedding'
|
|
1132
|
-
AND c.udt_name
|
|
1213
|
+
AND c.udt_name IN ('vector', 'halfvec')
|
|
1133
1214
|
)
|
|
1134
1215
|
AND EXISTS (
|
|
1135
1216
|
SELECT 1
|
|
@@ -1168,17 +1249,18 @@ var PgVector = class extends MastraVector {
|
|
|
1168
1249
|
try {
|
|
1169
1250
|
const { tableName } = this.getTableName(indexName);
|
|
1170
1251
|
const tableExistsQuery = `
|
|
1171
|
-
SELECT
|
|
1252
|
+
SELECT udt_name
|
|
1172
1253
|
FROM information_schema.columns
|
|
1173
1254
|
WHERE table_schema = $1
|
|
1174
1255
|
AND table_name = $2
|
|
1175
|
-
AND udt_name
|
|
1256
|
+
AND udt_name IN ('vector', 'halfvec')
|
|
1176
1257
|
LIMIT 1;
|
|
1177
1258
|
`;
|
|
1178
1259
|
const tableExists = await client.query(tableExistsQuery, [this.schema || "public", indexName]);
|
|
1179
1260
|
if (tableExists.rows.length === 0) {
|
|
1180
1261
|
throw new Error(`Vector table ${tableName} does not exist`);
|
|
1181
1262
|
}
|
|
1263
|
+
const vectorType = tableExists.rows[0].udt_name === "halfvec" ? "halfvec" : "vector";
|
|
1182
1264
|
const dimensionQuery = `
|
|
1183
1265
|
SELECT atttypmod as dimension
|
|
1184
1266
|
FROM pg_attribute
|
|
@@ -1228,6 +1310,7 @@ var PgVector = class extends MastraVector {
|
|
|
1228
1310
|
count: parseInt(countResult.rows[0].count),
|
|
1229
1311
|
metric,
|
|
1230
1312
|
type: index_method,
|
|
1313
|
+
vectorType,
|
|
1231
1314
|
config
|
|
1232
1315
|
};
|
|
1233
1316
|
} catch (e) {
|
|
@@ -1255,6 +1338,8 @@ var PgVector = class extends MastraVector {
|
|
|
1255
1338
|
const { tableName } = this.getTableName(indexName);
|
|
1256
1339
|
await client.query(`DROP TABLE IF EXISTS ${tableName} CASCADE`);
|
|
1257
1340
|
this.createdIndexes.delete(indexName);
|
|
1341
|
+
this.indexVectorTypes.delete(indexName);
|
|
1342
|
+
this.describeIndexCache.delete(indexName);
|
|
1258
1343
|
} catch (error) {
|
|
1259
1344
|
await client.query("ROLLBACK");
|
|
1260
1345
|
const mastraError = new MastraError(
|
|
@@ -1343,12 +1428,13 @@ var PgVector = class extends MastraVector {
|
|
|
1343
1428
|
}
|
|
1344
1429
|
client = await this.pool.connect();
|
|
1345
1430
|
const { tableName } = this.getTableName(indexName);
|
|
1346
|
-
const
|
|
1431
|
+
const indexInfo = await this.getIndexInfo({ indexName });
|
|
1432
|
+
const qualifiedVectorType = this.getVectorTypeName(indexInfo.vectorType);
|
|
1347
1433
|
let updateParts = [];
|
|
1348
1434
|
let values = [];
|
|
1349
1435
|
let valueIndex = 1;
|
|
1350
1436
|
if (update.vector) {
|
|
1351
|
-
updateParts.push(`embedding = $${valueIndex}::${
|
|
1437
|
+
updateParts.push(`embedding = $${valueIndex}::${qualifiedVectorType}`);
|
|
1352
1438
|
values.push(`[${update.vector.join(",")}]`);
|
|
1353
1439
|
valueIndex++;
|
|
1354
1440
|
}
|
|
@@ -1637,7 +1723,302 @@ function transformFromSqlRow({
|
|
|
1637
1723
|
return result;
|
|
1638
1724
|
}
|
|
1639
1725
|
|
|
1640
|
-
// src/storage/domains/
|
|
1726
|
+
// src/storage/domains/agents/index.ts
|
|
1727
|
+
var AgentsPG = class extends AgentsStorage {
|
|
1728
|
+
client;
|
|
1729
|
+
schema;
|
|
1730
|
+
constructor({ client, schema }) {
|
|
1731
|
+
super();
|
|
1732
|
+
this.client = client;
|
|
1733
|
+
this.schema = schema;
|
|
1734
|
+
}
|
|
1735
|
+
parseJson(value, fieldName) {
|
|
1736
|
+
if (!value) return void 0;
|
|
1737
|
+
if (typeof value !== "string") return value;
|
|
1738
|
+
try {
|
|
1739
|
+
return JSON.parse(value);
|
|
1740
|
+
} catch (error) {
|
|
1741
|
+
const details = {
|
|
1742
|
+
value: value.length > 100 ? value.substring(0, 100) + "..." : value
|
|
1743
|
+
};
|
|
1744
|
+
if (fieldName) {
|
|
1745
|
+
details.field = fieldName;
|
|
1746
|
+
}
|
|
1747
|
+
throw new MastraError(
|
|
1748
|
+
{
|
|
1749
|
+
id: createStorageErrorId("PG", "PARSE_JSON", "INVALID_JSON"),
|
|
1750
|
+
domain: ErrorDomain.STORAGE,
|
|
1751
|
+
category: ErrorCategory.SYSTEM,
|
|
1752
|
+
text: `Failed to parse JSON${fieldName ? ` for field "${fieldName}"` : ""}: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
1753
|
+
details
|
|
1754
|
+
},
|
|
1755
|
+
error
|
|
1756
|
+
);
|
|
1757
|
+
}
|
|
1758
|
+
}
|
|
1759
|
+
parseRow(row) {
|
|
1760
|
+
return {
|
|
1761
|
+
id: row.id,
|
|
1762
|
+
name: row.name,
|
|
1763
|
+
description: row.description,
|
|
1764
|
+
instructions: row.instructions,
|
|
1765
|
+
model: this.parseJson(row.model, "model"),
|
|
1766
|
+
tools: this.parseJson(row.tools, "tools"),
|
|
1767
|
+
defaultOptions: this.parseJson(row.defaultOptions, "defaultOptions"),
|
|
1768
|
+
workflows: this.parseJson(row.workflows, "workflows"),
|
|
1769
|
+
agents: this.parseJson(row.agents, "agents"),
|
|
1770
|
+
inputProcessors: this.parseJson(row.inputProcessors, "inputProcessors"),
|
|
1771
|
+
outputProcessors: this.parseJson(row.outputProcessors, "outputProcessors"),
|
|
1772
|
+
memory: this.parseJson(row.memory, "memory"),
|
|
1773
|
+
scorers: this.parseJson(row.scorers, "scorers"),
|
|
1774
|
+
metadata: this.parseJson(row.metadata, "metadata"),
|
|
1775
|
+
createdAt: row.createdAtZ || row.createdAt,
|
|
1776
|
+
updatedAt: row.updatedAtZ || row.updatedAt
|
|
1777
|
+
};
|
|
1778
|
+
}
|
|
1779
|
+
async getAgentById({ id }) {
|
|
1780
|
+
try {
|
|
1781
|
+
const tableName = getTableName({ indexName: TABLE_AGENTS, schemaName: getSchemaName(this.schema) });
|
|
1782
|
+
const result = await this.client.oneOrNone(`SELECT * FROM ${tableName} WHERE id = $1`, [id]);
|
|
1783
|
+
if (!result) {
|
|
1784
|
+
return null;
|
|
1785
|
+
}
|
|
1786
|
+
return this.parseRow(result);
|
|
1787
|
+
} catch (error) {
|
|
1788
|
+
throw new MastraError(
|
|
1789
|
+
{
|
|
1790
|
+
id: createStorageErrorId("PG", "GET_AGENT_BY_ID", "FAILED"),
|
|
1791
|
+
domain: ErrorDomain.STORAGE,
|
|
1792
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1793
|
+
details: { agentId: id }
|
|
1794
|
+
},
|
|
1795
|
+
error
|
|
1796
|
+
);
|
|
1797
|
+
}
|
|
1798
|
+
}
|
|
1799
|
+
async createAgent({ agent }) {
|
|
1800
|
+
try {
|
|
1801
|
+
const tableName = getTableName({ indexName: TABLE_AGENTS, schemaName: getSchemaName(this.schema) });
|
|
1802
|
+
const now = /* @__PURE__ */ new Date();
|
|
1803
|
+
const nowIso = now.toISOString();
|
|
1804
|
+
await this.client.none(
|
|
1805
|
+
`INSERT INTO ${tableName} (
|
|
1806
|
+
id, name, description, instructions, model, tools,
|
|
1807
|
+
"defaultOptions", workflows, agents, "inputProcessors", "outputProcessors", memory, scorers, metadata,
|
|
1808
|
+
"createdAt", "createdAtZ", "updatedAt", "updatedAtZ"
|
|
1809
|
+
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18)`,
|
|
1810
|
+
[
|
|
1811
|
+
agent.id,
|
|
1812
|
+
agent.name,
|
|
1813
|
+
agent.description ?? null,
|
|
1814
|
+
agent.instructions,
|
|
1815
|
+
JSON.stringify(agent.model),
|
|
1816
|
+
agent.tools ? JSON.stringify(agent.tools) : null,
|
|
1817
|
+
agent.defaultOptions ? JSON.stringify(agent.defaultOptions) : null,
|
|
1818
|
+
agent.workflows ? JSON.stringify(agent.workflows) : null,
|
|
1819
|
+
agent.agents ? JSON.stringify(agent.agents) : null,
|
|
1820
|
+
agent.inputProcessors ? JSON.stringify(agent.inputProcessors) : null,
|
|
1821
|
+
agent.outputProcessors ? JSON.stringify(agent.outputProcessors) : null,
|
|
1822
|
+
agent.memory ? JSON.stringify(agent.memory) : null,
|
|
1823
|
+
agent.scorers ? JSON.stringify(agent.scorers) : null,
|
|
1824
|
+
agent.metadata ? JSON.stringify(agent.metadata) : null,
|
|
1825
|
+
nowIso,
|
|
1826
|
+
nowIso,
|
|
1827
|
+
nowIso,
|
|
1828
|
+
nowIso
|
|
1829
|
+
]
|
|
1830
|
+
);
|
|
1831
|
+
return {
|
|
1832
|
+
...agent,
|
|
1833
|
+
createdAt: now,
|
|
1834
|
+
updatedAt: now
|
|
1835
|
+
};
|
|
1836
|
+
} catch (error) {
|
|
1837
|
+
throw new MastraError(
|
|
1838
|
+
{
|
|
1839
|
+
id: createStorageErrorId("PG", "CREATE_AGENT", "FAILED"),
|
|
1840
|
+
domain: ErrorDomain.STORAGE,
|
|
1841
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1842
|
+
details: { agentId: agent.id }
|
|
1843
|
+
},
|
|
1844
|
+
error
|
|
1845
|
+
);
|
|
1846
|
+
}
|
|
1847
|
+
}
|
|
1848
|
+
async updateAgent({ id, ...updates }) {
|
|
1849
|
+
try {
|
|
1850
|
+
const tableName = getTableName({ indexName: TABLE_AGENTS, schemaName: getSchemaName(this.schema) });
|
|
1851
|
+
const existingAgent = await this.getAgentById({ id });
|
|
1852
|
+
if (!existingAgent) {
|
|
1853
|
+
throw new MastraError({
|
|
1854
|
+
id: createStorageErrorId("PG", "UPDATE_AGENT", "NOT_FOUND"),
|
|
1855
|
+
domain: ErrorDomain.STORAGE,
|
|
1856
|
+
category: ErrorCategory.USER,
|
|
1857
|
+
text: `Agent ${id} not found`,
|
|
1858
|
+
details: { agentId: id }
|
|
1859
|
+
});
|
|
1860
|
+
}
|
|
1861
|
+
const setClauses = [];
|
|
1862
|
+
const values = [];
|
|
1863
|
+
let paramIndex = 1;
|
|
1864
|
+
if (updates.name !== void 0) {
|
|
1865
|
+
setClauses.push(`name = $${paramIndex++}`);
|
|
1866
|
+
values.push(updates.name);
|
|
1867
|
+
}
|
|
1868
|
+
if (updates.description !== void 0) {
|
|
1869
|
+
setClauses.push(`description = $${paramIndex++}`);
|
|
1870
|
+
values.push(updates.description);
|
|
1871
|
+
}
|
|
1872
|
+
if (updates.instructions !== void 0) {
|
|
1873
|
+
setClauses.push(`instructions = $${paramIndex++}`);
|
|
1874
|
+
values.push(updates.instructions);
|
|
1875
|
+
}
|
|
1876
|
+
if (updates.model !== void 0) {
|
|
1877
|
+
setClauses.push(`model = $${paramIndex++}`);
|
|
1878
|
+
values.push(JSON.stringify(updates.model));
|
|
1879
|
+
}
|
|
1880
|
+
if (updates.tools !== void 0) {
|
|
1881
|
+
setClauses.push(`tools = $${paramIndex++}`);
|
|
1882
|
+
values.push(JSON.stringify(updates.tools));
|
|
1883
|
+
}
|
|
1884
|
+
if (updates.defaultOptions !== void 0) {
|
|
1885
|
+
setClauses.push(`"defaultOptions" = $${paramIndex++}`);
|
|
1886
|
+
values.push(JSON.stringify(updates.defaultOptions));
|
|
1887
|
+
}
|
|
1888
|
+
if (updates.workflows !== void 0) {
|
|
1889
|
+
setClauses.push(`workflows = $${paramIndex++}`);
|
|
1890
|
+
values.push(JSON.stringify(updates.workflows));
|
|
1891
|
+
}
|
|
1892
|
+
if (updates.agents !== void 0) {
|
|
1893
|
+
setClauses.push(`agents = $${paramIndex++}`);
|
|
1894
|
+
values.push(JSON.stringify(updates.agents));
|
|
1895
|
+
}
|
|
1896
|
+
if (updates.inputProcessors !== void 0) {
|
|
1897
|
+
setClauses.push(`"inputProcessors" = $${paramIndex++}`);
|
|
1898
|
+
values.push(JSON.stringify(updates.inputProcessors));
|
|
1899
|
+
}
|
|
1900
|
+
if (updates.outputProcessors !== void 0) {
|
|
1901
|
+
setClauses.push(`"outputProcessors" = $${paramIndex++}`);
|
|
1902
|
+
values.push(JSON.stringify(updates.outputProcessors));
|
|
1903
|
+
}
|
|
1904
|
+
if (updates.memory !== void 0) {
|
|
1905
|
+
setClauses.push(`memory = $${paramIndex++}`);
|
|
1906
|
+
values.push(JSON.stringify(updates.memory));
|
|
1907
|
+
}
|
|
1908
|
+
if (updates.scorers !== void 0) {
|
|
1909
|
+
setClauses.push(`scorers = $${paramIndex++}`);
|
|
1910
|
+
values.push(JSON.stringify(updates.scorers));
|
|
1911
|
+
}
|
|
1912
|
+
if (updates.metadata !== void 0) {
|
|
1913
|
+
const mergedMetadata = { ...existingAgent.metadata, ...updates.metadata };
|
|
1914
|
+
setClauses.push(`metadata = $${paramIndex++}`);
|
|
1915
|
+
values.push(JSON.stringify(mergedMetadata));
|
|
1916
|
+
}
|
|
1917
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1918
|
+
setClauses.push(`"updatedAt" = $${paramIndex++}`);
|
|
1919
|
+
values.push(now);
|
|
1920
|
+
setClauses.push(`"updatedAtZ" = $${paramIndex++}`);
|
|
1921
|
+
values.push(now);
|
|
1922
|
+
values.push(id);
|
|
1923
|
+
if (setClauses.length > 2) {
|
|
1924
|
+
await this.client.none(`UPDATE ${tableName} SET ${setClauses.join(", ")} WHERE id = $${paramIndex}`, values);
|
|
1925
|
+
}
|
|
1926
|
+
const updatedAgent = await this.getAgentById({ id });
|
|
1927
|
+
if (!updatedAgent) {
|
|
1928
|
+
throw new MastraError({
|
|
1929
|
+
id: createStorageErrorId("PG", "UPDATE_AGENT", "NOT_FOUND_AFTER_UPDATE"),
|
|
1930
|
+
domain: ErrorDomain.STORAGE,
|
|
1931
|
+
category: ErrorCategory.SYSTEM,
|
|
1932
|
+
text: `Agent ${id} not found after update`,
|
|
1933
|
+
details: { agentId: id }
|
|
1934
|
+
});
|
|
1935
|
+
}
|
|
1936
|
+
return updatedAgent;
|
|
1937
|
+
} catch (error) {
|
|
1938
|
+
if (error instanceof MastraError) {
|
|
1939
|
+
throw error;
|
|
1940
|
+
}
|
|
1941
|
+
throw new MastraError(
|
|
1942
|
+
{
|
|
1943
|
+
id: createStorageErrorId("PG", "UPDATE_AGENT", "FAILED"),
|
|
1944
|
+
domain: ErrorDomain.STORAGE,
|
|
1945
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1946
|
+
details: { agentId: id }
|
|
1947
|
+
},
|
|
1948
|
+
error
|
|
1949
|
+
);
|
|
1950
|
+
}
|
|
1951
|
+
}
|
|
1952
|
+
async deleteAgent({ id }) {
|
|
1953
|
+
try {
|
|
1954
|
+
const tableName = getTableName({ indexName: TABLE_AGENTS, schemaName: getSchemaName(this.schema) });
|
|
1955
|
+
await this.client.none(`DELETE FROM ${tableName} WHERE id = $1`, [id]);
|
|
1956
|
+
} catch (error) {
|
|
1957
|
+
throw new MastraError(
|
|
1958
|
+
{
|
|
1959
|
+
id: createStorageErrorId("PG", "DELETE_AGENT", "FAILED"),
|
|
1960
|
+
domain: ErrorDomain.STORAGE,
|
|
1961
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1962
|
+
details: { agentId: id }
|
|
1963
|
+
},
|
|
1964
|
+
error
|
|
1965
|
+
);
|
|
1966
|
+
}
|
|
1967
|
+
}
|
|
1968
|
+
async listAgents(args) {
|
|
1969
|
+
const { page = 0, perPage: perPageInput, orderBy } = args || {};
|
|
1970
|
+
const { field, direction } = this.parseOrderBy(orderBy);
|
|
1971
|
+
if (page < 0) {
|
|
1972
|
+
throw new MastraError(
|
|
1973
|
+
{
|
|
1974
|
+
id: createStorageErrorId("PG", "LIST_AGENTS", "INVALID_PAGE"),
|
|
1975
|
+
domain: ErrorDomain.STORAGE,
|
|
1976
|
+
category: ErrorCategory.USER,
|
|
1977
|
+
details: { page }
|
|
1978
|
+
},
|
|
1979
|
+
new Error("page must be >= 0")
|
|
1980
|
+
);
|
|
1981
|
+
}
|
|
1982
|
+
const perPage = normalizePerPage(perPageInput, 100);
|
|
1983
|
+
const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
|
|
1984
|
+
try {
|
|
1985
|
+
const tableName = getTableName({ indexName: TABLE_AGENTS, schemaName: getSchemaName(this.schema) });
|
|
1986
|
+
const countResult = await this.client.one(`SELECT COUNT(*) as count FROM ${tableName}`);
|
|
1987
|
+
const total = parseInt(countResult.count, 10);
|
|
1988
|
+
if (total === 0) {
|
|
1989
|
+
return {
|
|
1990
|
+
agents: [],
|
|
1991
|
+
total: 0,
|
|
1992
|
+
page,
|
|
1993
|
+
perPage: perPageForResponse,
|
|
1994
|
+
hasMore: false
|
|
1995
|
+
};
|
|
1996
|
+
}
|
|
1997
|
+
const limitValue = perPageInput === false ? total : perPage;
|
|
1998
|
+
const dataResult = await this.client.manyOrNone(
|
|
1999
|
+
`SELECT * FROM ${tableName} ORDER BY "${field}" ${direction} LIMIT $1 OFFSET $2`,
|
|
2000
|
+
[limitValue, offset]
|
|
2001
|
+
);
|
|
2002
|
+
const agents = (dataResult || []).map((row) => this.parseRow(row));
|
|
2003
|
+
return {
|
|
2004
|
+
agents,
|
|
2005
|
+
total,
|
|
2006
|
+
page,
|
|
2007
|
+
perPage: perPageForResponse,
|
|
2008
|
+
hasMore: perPageInput === false ? false : offset + perPage < total
|
|
2009
|
+
};
|
|
2010
|
+
} catch (error) {
|
|
2011
|
+
throw new MastraError(
|
|
2012
|
+
{
|
|
2013
|
+
id: createStorageErrorId("PG", "LIST_AGENTS", "FAILED"),
|
|
2014
|
+
domain: ErrorDomain.STORAGE,
|
|
2015
|
+
category: ErrorCategory.THIRD_PARTY
|
|
2016
|
+
},
|
|
2017
|
+
error
|
|
2018
|
+
);
|
|
2019
|
+
}
|
|
2020
|
+
}
|
|
2021
|
+
};
|
|
1641
2022
|
var MemoryPG = class extends MemoryStorage {
|
|
1642
2023
|
client;
|
|
1643
2024
|
schema;
|
|
@@ -4053,6 +4434,27 @@ var WorkflowsPG = class extends WorkflowsStorage {
|
|
|
4053
4434
|
);
|
|
4054
4435
|
}
|
|
4055
4436
|
}
|
|
4437
|
+
async deleteWorkflowRunById({ runId, workflowName }) {
|
|
4438
|
+
try {
|
|
4439
|
+
await this.client.none(
|
|
4440
|
+
`DELETE FROM ${getTableName({ indexName: TABLE_WORKFLOW_SNAPSHOT, schemaName: this.schema })} WHERE run_id = $1 AND workflow_name = $2`,
|
|
4441
|
+
[runId, workflowName]
|
|
4442
|
+
);
|
|
4443
|
+
} catch (error) {
|
|
4444
|
+
throw new MastraError(
|
|
4445
|
+
{
|
|
4446
|
+
id: createStorageErrorId("PG", "DELETE_WORKFLOW_RUN_BY_ID", "FAILED"),
|
|
4447
|
+
domain: ErrorDomain.STORAGE,
|
|
4448
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
4449
|
+
details: {
|
|
4450
|
+
runId,
|
|
4451
|
+
workflowName
|
|
4452
|
+
}
|
|
4453
|
+
},
|
|
4454
|
+
error
|
|
4455
|
+
);
|
|
4456
|
+
}
|
|
4457
|
+
}
|
|
4056
4458
|
async listWorkflowRuns({
|
|
4057
4459
|
workflowName,
|
|
4058
4460
|
fromDate,
|
|
@@ -4188,12 +4590,14 @@ var PostgresStore = class extends MastraStorage {
|
|
|
4188
4590
|
const workflows = new WorkflowsPG({ client: this.#db, operations, schema: this.schema });
|
|
4189
4591
|
const memory = new MemoryPG({ client: this.#db, schema: this.schema, operations });
|
|
4190
4592
|
const observability = new ObservabilityPG({ client: this.#db, operations, schema: this.schema });
|
|
4593
|
+
const agents = new AgentsPG({ client: this.#db, schema: this.schema });
|
|
4191
4594
|
this.stores = {
|
|
4192
4595
|
operations,
|
|
4193
4596
|
scores,
|
|
4194
4597
|
workflows,
|
|
4195
4598
|
memory,
|
|
4196
|
-
observability
|
|
4599
|
+
observability,
|
|
4600
|
+
agents
|
|
4197
4601
|
};
|
|
4198
4602
|
} catch (e) {
|
|
4199
4603
|
throw new MastraError(
|
|
@@ -4245,7 +4649,8 @@ var PostgresStore = class extends MastraStorage {
|
|
|
4245
4649
|
deleteMessages: true,
|
|
4246
4650
|
observabilityInstance: true,
|
|
4247
4651
|
indexManagement: true,
|
|
4248
|
-
listScoresBySpan: true
|
|
4652
|
+
listScoresBySpan: true,
|
|
4653
|
+
agents: true
|
|
4249
4654
|
};
|
|
4250
4655
|
}
|
|
4251
4656
|
async createTable({
|
|
@@ -4364,6 +4769,9 @@ var PostgresStore = class extends MastraStorage {
|
|
|
4364
4769
|
}) {
|
|
4365
4770
|
return this.stores.workflows.getWorkflowRunById({ runId, workflowName });
|
|
4366
4771
|
}
|
|
4772
|
+
async deleteWorkflowRunById({ runId, workflowName }) {
|
|
4773
|
+
return this.stores.workflows.deleteWorkflowRunById({ runId, workflowName });
|
|
4774
|
+
}
|
|
4367
4775
|
async close() {
|
|
4368
4776
|
this.pgp.end();
|
|
4369
4777
|
}
|