@mastra/pg 0.16.1 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -0
- package/dist/index.cjs +784 -42
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +785 -43
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/observability/index.d.ts +44 -0
- package/dist/storage/domains/observability/index.d.ts.map +1 -0
- package/dist/storage/domains/operations/index.d.ts +41 -0
- package/dist/storage/domains/operations/index.d.ts.map +1 -1
- package/dist/storage/domains/scores/index.d.ts +8 -0
- package/dist/storage/domains/scores/index.d.ts.map +1 -1
- package/dist/storage/domains/utils.d.ts +19 -0
- package/dist/storage/domains/utils.d.ts.map +1 -1
- package/dist/storage/index.d.ts +42 -5
- package/dist/storage/index.d.ts.map +1 -1
- package/package.json +6 -6
package/dist/index.cjs
CHANGED
|
@@ -10,6 +10,7 @@ var filter = require('@mastra/core/vector/filter');
|
|
|
10
10
|
var storage = require('@mastra/core/storage');
|
|
11
11
|
var pgPromise = require('pg-promise');
|
|
12
12
|
var agent = require('@mastra/core/agent');
|
|
13
|
+
var scores = require('@mastra/core/scores');
|
|
13
14
|
|
|
14
15
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
15
16
|
|
|
@@ -1266,6 +1267,68 @@ function getTableName({ indexName, schemaName }) {
|
|
|
1266
1267
|
const quotedSchemaName = schemaName;
|
|
1267
1268
|
return quotedSchemaName ? `${quotedSchemaName}.${quotedIndexName}` : quotedIndexName;
|
|
1268
1269
|
}
|
|
1270
|
+
function buildDateRangeFilter(dateRange, fieldName) {
|
|
1271
|
+
const filters = {};
|
|
1272
|
+
if (dateRange?.start) {
|
|
1273
|
+
filters[`${fieldName}_gte`] = dateRange.start;
|
|
1274
|
+
}
|
|
1275
|
+
if (dateRange?.end) {
|
|
1276
|
+
filters[`${fieldName}_lte`] = dateRange.end;
|
|
1277
|
+
}
|
|
1278
|
+
return filters;
|
|
1279
|
+
}
|
|
1280
|
+
function prepareWhereClause(filters, _schema) {
|
|
1281
|
+
const conditions = [];
|
|
1282
|
+
const args = [];
|
|
1283
|
+
let paramIndex = 1;
|
|
1284
|
+
Object.entries(filters).forEach(([key, value]) => {
|
|
1285
|
+
if (value === void 0) return;
|
|
1286
|
+
if (key.endsWith("_gte")) {
|
|
1287
|
+
const fieldName = key.slice(0, -4);
|
|
1288
|
+
conditions.push(`"${utils.parseSqlIdentifier(fieldName, "field name")}" >= $${paramIndex++}`);
|
|
1289
|
+
args.push(value instanceof Date ? value.toISOString() : value);
|
|
1290
|
+
} else if (key.endsWith("_lte")) {
|
|
1291
|
+
const fieldName = key.slice(0, -4);
|
|
1292
|
+
conditions.push(`"${utils.parseSqlIdentifier(fieldName, "field name")}" <= $${paramIndex++}`);
|
|
1293
|
+
args.push(value instanceof Date ? value.toISOString() : value);
|
|
1294
|
+
} else if (value === null) {
|
|
1295
|
+
conditions.push(`"${utils.parseSqlIdentifier(key, "field name")}" IS NULL`);
|
|
1296
|
+
} else {
|
|
1297
|
+
conditions.push(`"${utils.parseSqlIdentifier(key, "field name")}" = $${paramIndex++}`);
|
|
1298
|
+
args.push(value instanceof Date ? value.toISOString() : value);
|
|
1299
|
+
}
|
|
1300
|
+
});
|
|
1301
|
+
return {
|
|
1302
|
+
sql: conditions.length > 0 ? ` WHERE ${conditions.join(" AND ")}` : "",
|
|
1303
|
+
args
|
|
1304
|
+
};
|
|
1305
|
+
}
|
|
1306
|
+
function transformFromSqlRow({
|
|
1307
|
+
tableName,
|
|
1308
|
+
sqlRow
|
|
1309
|
+
}) {
|
|
1310
|
+
const schema = storage.TABLE_SCHEMAS[tableName];
|
|
1311
|
+
const result = {};
|
|
1312
|
+
Object.entries(sqlRow).forEach(([key, value]) => {
|
|
1313
|
+
const columnSchema = schema?.[key];
|
|
1314
|
+
if (columnSchema?.type === "jsonb" && typeof value === "string") {
|
|
1315
|
+
try {
|
|
1316
|
+
result[key] = JSON.parse(value);
|
|
1317
|
+
} catch {
|
|
1318
|
+
result[key] = value;
|
|
1319
|
+
}
|
|
1320
|
+
} else if (columnSchema?.type === "timestamp" && value && typeof value === "string") {
|
|
1321
|
+
result[key] = new Date(value);
|
|
1322
|
+
} else if (columnSchema?.type === "timestamp" && value instanceof Date) {
|
|
1323
|
+
result[key] = value;
|
|
1324
|
+
} else if (columnSchema?.type === "boolean") {
|
|
1325
|
+
result[key] = Boolean(value);
|
|
1326
|
+
} else {
|
|
1327
|
+
result[key] = value;
|
|
1328
|
+
}
|
|
1329
|
+
});
|
|
1330
|
+
return result;
|
|
1331
|
+
}
|
|
1269
1332
|
|
|
1270
1333
|
// src/storage/domains/legacy-evals/index.ts
|
|
1271
1334
|
function transformEvalRow(row) {
|
|
@@ -2201,6 +2264,316 @@ var MemoryPG = class extends storage.MemoryStorage {
|
|
|
2201
2264
|
return updatedResource;
|
|
2202
2265
|
}
|
|
2203
2266
|
};
|
|
2267
|
+
var ObservabilityPG = class extends storage.ObservabilityStorage {
|
|
2268
|
+
client;
|
|
2269
|
+
operations;
|
|
2270
|
+
schema;
|
|
2271
|
+
constructor({
|
|
2272
|
+
client,
|
|
2273
|
+
operations,
|
|
2274
|
+
schema
|
|
2275
|
+
}) {
|
|
2276
|
+
super();
|
|
2277
|
+
this.client = client;
|
|
2278
|
+
this.operations = operations;
|
|
2279
|
+
this.schema = schema;
|
|
2280
|
+
}
|
|
2281
|
+
get aiTracingStrategy() {
|
|
2282
|
+
return {
|
|
2283
|
+
preferred: "batch-with-updates",
|
|
2284
|
+
supported: ["batch-with-updates", "insert-only"]
|
|
2285
|
+
};
|
|
2286
|
+
}
|
|
2287
|
+
async createAISpan(span) {
|
|
2288
|
+
try {
|
|
2289
|
+
const startedAt = span.startedAt instanceof Date ? span.startedAt.toISOString() : span.startedAt;
|
|
2290
|
+
const endedAt = span.endedAt instanceof Date ? span.endedAt.toISOString() : span.endedAt;
|
|
2291
|
+
const record = {
|
|
2292
|
+
...span,
|
|
2293
|
+
startedAt,
|
|
2294
|
+
endedAt,
|
|
2295
|
+
startedAtZ: startedAt,
|
|
2296
|
+
endedAtZ: endedAt
|
|
2297
|
+
// Note: createdAt/updatedAt will be set by database triggers
|
|
2298
|
+
};
|
|
2299
|
+
return this.operations.insert({ tableName: storage.TABLE_AI_SPANS, record });
|
|
2300
|
+
} catch (error$1) {
|
|
2301
|
+
throw new error.MastraError(
|
|
2302
|
+
{
|
|
2303
|
+
id: "PG_STORE_CREATE_AI_SPAN_FAILED",
|
|
2304
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2305
|
+
category: error.ErrorCategory.USER,
|
|
2306
|
+
details: {
|
|
2307
|
+
spanId: span.spanId,
|
|
2308
|
+
traceId: span.traceId,
|
|
2309
|
+
spanType: span.spanType,
|
|
2310
|
+
spanName: span.name
|
|
2311
|
+
}
|
|
2312
|
+
},
|
|
2313
|
+
error$1
|
|
2314
|
+
);
|
|
2315
|
+
}
|
|
2316
|
+
}
|
|
2317
|
+
async getAITrace(traceId) {
|
|
2318
|
+
try {
|
|
2319
|
+
const tableName = getTableName({
|
|
2320
|
+
indexName: storage.TABLE_AI_SPANS,
|
|
2321
|
+
schemaName: getSchemaName(this.schema)
|
|
2322
|
+
});
|
|
2323
|
+
const spans = await this.client.manyOrNone(
|
|
2324
|
+
`SELECT
|
|
2325
|
+
"traceId", "spanId", "parentSpanId", "name", "scope", "spanType",
|
|
2326
|
+
"attributes", "metadata", "links", "input", "output", "error", "isEvent",
|
|
2327
|
+
"startedAtZ" as "startedAt", "endedAtZ" as "endedAt",
|
|
2328
|
+
"createdAtZ" as "createdAt", "updatedAtZ" as "updatedAt"
|
|
2329
|
+
FROM ${tableName}
|
|
2330
|
+
WHERE "traceId" = $1
|
|
2331
|
+
ORDER BY "startedAtZ" DESC`,
|
|
2332
|
+
[traceId]
|
|
2333
|
+
);
|
|
2334
|
+
if (!spans || spans.length === 0) {
|
|
2335
|
+
return null;
|
|
2336
|
+
}
|
|
2337
|
+
return {
|
|
2338
|
+
traceId,
|
|
2339
|
+
spans: spans.map(
|
|
2340
|
+
(span) => transformFromSqlRow({
|
|
2341
|
+
tableName: storage.TABLE_AI_SPANS,
|
|
2342
|
+
sqlRow: span
|
|
2343
|
+
})
|
|
2344
|
+
)
|
|
2345
|
+
};
|
|
2346
|
+
} catch (error$1) {
|
|
2347
|
+
throw new error.MastraError(
|
|
2348
|
+
{
|
|
2349
|
+
id: "PG_STORE_GET_AI_TRACE_FAILED",
|
|
2350
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2351
|
+
category: error.ErrorCategory.USER,
|
|
2352
|
+
details: {
|
|
2353
|
+
traceId
|
|
2354
|
+
}
|
|
2355
|
+
},
|
|
2356
|
+
error$1
|
|
2357
|
+
);
|
|
2358
|
+
}
|
|
2359
|
+
}
|
|
2360
|
+
async updateAISpan({
|
|
2361
|
+
spanId,
|
|
2362
|
+
traceId,
|
|
2363
|
+
updates
|
|
2364
|
+
}) {
|
|
2365
|
+
try {
|
|
2366
|
+
const data = { ...updates };
|
|
2367
|
+
if (data.endedAt instanceof Date) {
|
|
2368
|
+
data.endedAt = data.endedAt.toISOString();
|
|
2369
|
+
}
|
|
2370
|
+
if (data.startedAt instanceof Date) {
|
|
2371
|
+
data.startedAt = data.startedAt.toISOString();
|
|
2372
|
+
}
|
|
2373
|
+
await this.operations.update({
|
|
2374
|
+
tableName: storage.TABLE_AI_SPANS,
|
|
2375
|
+
keys: { spanId, traceId },
|
|
2376
|
+
data
|
|
2377
|
+
});
|
|
2378
|
+
} catch (error$1) {
|
|
2379
|
+
throw new error.MastraError(
|
|
2380
|
+
{
|
|
2381
|
+
id: "PG_STORE_UPDATE_AI_SPAN_FAILED",
|
|
2382
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2383
|
+
category: error.ErrorCategory.USER,
|
|
2384
|
+
details: {
|
|
2385
|
+
spanId,
|
|
2386
|
+
traceId
|
|
2387
|
+
}
|
|
2388
|
+
},
|
|
2389
|
+
error$1
|
|
2390
|
+
);
|
|
2391
|
+
}
|
|
2392
|
+
}
|
|
2393
|
+
async getAITracesPaginated({
|
|
2394
|
+
filters,
|
|
2395
|
+
pagination
|
|
2396
|
+
}) {
|
|
2397
|
+
const page = pagination?.page ?? 0;
|
|
2398
|
+
const perPage = pagination?.perPage ?? 10;
|
|
2399
|
+
const { entityId, entityType, ...actualFilters } = filters || {};
|
|
2400
|
+
const filtersWithDateRange = {
|
|
2401
|
+
...actualFilters,
|
|
2402
|
+
...buildDateRangeFilter(pagination?.dateRange, "startedAtZ"),
|
|
2403
|
+
parentSpanId: null
|
|
2404
|
+
// Only get root spans for traces
|
|
2405
|
+
};
|
|
2406
|
+
const whereClause = prepareWhereClause(filtersWithDateRange);
|
|
2407
|
+
let actualWhereClause = whereClause.sql;
|
|
2408
|
+
let currentParamIndex = whereClause.args.length + 1;
|
|
2409
|
+
if (entityId && entityType) {
|
|
2410
|
+
let name = "";
|
|
2411
|
+
if (entityType === "workflow") {
|
|
2412
|
+
name = `workflow run: '${entityId}'`;
|
|
2413
|
+
} else if (entityType === "agent") {
|
|
2414
|
+
name = `agent run: '${entityId}'`;
|
|
2415
|
+
} else {
|
|
2416
|
+
const error$1 = new error.MastraError({
|
|
2417
|
+
id: "PG_STORE_GET_AI_TRACES_PAGINATED_FAILED",
|
|
2418
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2419
|
+
category: error.ErrorCategory.USER,
|
|
2420
|
+
details: {
|
|
2421
|
+
entityType
|
|
2422
|
+
},
|
|
2423
|
+
text: `Cannot filter by entity type: ${entityType}`
|
|
2424
|
+
});
|
|
2425
|
+
this.logger?.trackException(error$1);
|
|
2426
|
+
throw error$1;
|
|
2427
|
+
}
|
|
2428
|
+
whereClause.args.push(name);
|
|
2429
|
+
const statement = `"name" = $${currentParamIndex++}`;
|
|
2430
|
+
if (actualWhereClause) {
|
|
2431
|
+
actualWhereClause += ` AND ${statement}`;
|
|
2432
|
+
} else {
|
|
2433
|
+
actualWhereClause = ` WHERE ${statement}`;
|
|
2434
|
+
}
|
|
2435
|
+
}
|
|
2436
|
+
const tableName = getTableName({
|
|
2437
|
+
indexName: storage.TABLE_AI_SPANS,
|
|
2438
|
+
schemaName: getSchemaName(this.schema)
|
|
2439
|
+
});
|
|
2440
|
+
try {
|
|
2441
|
+
const countResult = await this.client.oneOrNone(
|
|
2442
|
+
`SELECT COUNT(*) FROM ${tableName}${actualWhereClause}`,
|
|
2443
|
+
whereClause.args
|
|
2444
|
+
);
|
|
2445
|
+
const count = Number(countResult?.count ?? 0);
|
|
2446
|
+
if (count === 0) {
|
|
2447
|
+
return {
|
|
2448
|
+
pagination: {
|
|
2449
|
+
total: 0,
|
|
2450
|
+
page,
|
|
2451
|
+
perPage,
|
|
2452
|
+
hasMore: false
|
|
2453
|
+
},
|
|
2454
|
+
spans: []
|
|
2455
|
+
};
|
|
2456
|
+
}
|
|
2457
|
+
const spans = await this.client.manyOrNone(
|
|
2458
|
+
`SELECT
|
|
2459
|
+
"traceId", "spanId", "parentSpanId", "name", "scope", "spanType",
|
|
2460
|
+
"attributes", "metadata", "links", "input", "output", "error", "isEvent",
|
|
2461
|
+
"startedAtZ" as "startedAt", "endedAtZ" as "endedAt",
|
|
2462
|
+
"createdAtZ" as "createdAt", "updatedAtZ" as "updatedAt"
|
|
2463
|
+
FROM ${tableName}${actualWhereClause}
|
|
2464
|
+
ORDER BY "startedAtZ" DESC
|
|
2465
|
+
LIMIT $${currentParamIndex} OFFSET $${currentParamIndex + 1}`,
|
|
2466
|
+
[...whereClause.args, perPage, page * perPage]
|
|
2467
|
+
);
|
|
2468
|
+
return {
|
|
2469
|
+
pagination: {
|
|
2470
|
+
total: count,
|
|
2471
|
+
page,
|
|
2472
|
+
perPage,
|
|
2473
|
+
hasMore: spans.length === perPage
|
|
2474
|
+
},
|
|
2475
|
+
spans: spans.map(
|
|
2476
|
+
(span) => transformFromSqlRow({
|
|
2477
|
+
tableName: storage.TABLE_AI_SPANS,
|
|
2478
|
+
sqlRow: span
|
|
2479
|
+
})
|
|
2480
|
+
)
|
|
2481
|
+
};
|
|
2482
|
+
} catch (error$1) {
|
|
2483
|
+
throw new error.MastraError(
|
|
2484
|
+
{
|
|
2485
|
+
id: "PG_STORE_GET_AI_TRACES_PAGINATED_FAILED",
|
|
2486
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2487
|
+
category: error.ErrorCategory.USER
|
|
2488
|
+
},
|
|
2489
|
+
error$1
|
|
2490
|
+
);
|
|
2491
|
+
}
|
|
2492
|
+
}
|
|
2493
|
+
async batchCreateAISpans(args) {
|
|
2494
|
+
try {
|
|
2495
|
+
const records = args.records.map((record) => {
|
|
2496
|
+
const startedAt = record.startedAt instanceof Date ? record.startedAt.toISOString() : record.startedAt;
|
|
2497
|
+
const endedAt = record.endedAt instanceof Date ? record.endedAt.toISOString() : record.endedAt;
|
|
2498
|
+
return {
|
|
2499
|
+
...record,
|
|
2500
|
+
startedAt,
|
|
2501
|
+
endedAt,
|
|
2502
|
+
startedAtZ: startedAt,
|
|
2503
|
+
endedAtZ: endedAt
|
|
2504
|
+
// Note: createdAt/updatedAt will be set by database triggers
|
|
2505
|
+
};
|
|
2506
|
+
});
|
|
2507
|
+
return this.operations.batchInsert({
|
|
2508
|
+
tableName: storage.TABLE_AI_SPANS,
|
|
2509
|
+
records
|
|
2510
|
+
});
|
|
2511
|
+
} catch (error$1) {
|
|
2512
|
+
throw new error.MastraError(
|
|
2513
|
+
{
|
|
2514
|
+
id: "PG_STORE_BATCH_CREATE_AI_SPANS_FAILED",
|
|
2515
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2516
|
+
category: error.ErrorCategory.USER
|
|
2517
|
+
},
|
|
2518
|
+
error$1
|
|
2519
|
+
);
|
|
2520
|
+
}
|
|
2521
|
+
}
|
|
2522
|
+
async batchUpdateAISpans(args) {
|
|
2523
|
+
try {
|
|
2524
|
+
return this.operations.batchUpdate({
|
|
2525
|
+
tableName: storage.TABLE_AI_SPANS,
|
|
2526
|
+
updates: args.records.map((record) => {
|
|
2527
|
+
const data = {
|
|
2528
|
+
...record.updates
|
|
2529
|
+
};
|
|
2530
|
+
if (data.endedAt instanceof Date) {
|
|
2531
|
+
const endedAt = data.endedAt.toISOString();
|
|
2532
|
+
data.endedAt = endedAt;
|
|
2533
|
+
data.endedAtZ = endedAt;
|
|
2534
|
+
}
|
|
2535
|
+
if (data.startedAt instanceof Date) {
|
|
2536
|
+
const startedAt = data.startedAt.toISOString();
|
|
2537
|
+
data.startedAt = startedAt;
|
|
2538
|
+
data.startedAtZ = startedAt;
|
|
2539
|
+
}
|
|
2540
|
+
return {
|
|
2541
|
+
keys: { spanId: record.spanId, traceId: record.traceId },
|
|
2542
|
+
data
|
|
2543
|
+
};
|
|
2544
|
+
})
|
|
2545
|
+
});
|
|
2546
|
+
} catch (error$1) {
|
|
2547
|
+
throw new error.MastraError(
|
|
2548
|
+
{
|
|
2549
|
+
id: "PG_STORE_BATCH_UPDATE_AI_SPANS_FAILED",
|
|
2550
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2551
|
+
category: error.ErrorCategory.USER
|
|
2552
|
+
},
|
|
2553
|
+
error$1
|
|
2554
|
+
);
|
|
2555
|
+
}
|
|
2556
|
+
}
|
|
2557
|
+
async batchDeleteAITraces(args) {
|
|
2558
|
+
try {
|
|
2559
|
+
const tableName = getTableName({
|
|
2560
|
+
indexName: storage.TABLE_AI_SPANS,
|
|
2561
|
+
schemaName: getSchemaName(this.schema)
|
|
2562
|
+
});
|
|
2563
|
+
const placeholders = args.traceIds.map((_, i) => `$${i + 1}`).join(", ");
|
|
2564
|
+
await this.client.none(`DELETE FROM ${tableName} WHERE "traceId" IN (${placeholders})`, args.traceIds);
|
|
2565
|
+
} catch (error$1) {
|
|
2566
|
+
throw new error.MastraError(
|
|
2567
|
+
{
|
|
2568
|
+
id: "PG_STORE_BATCH_DELETE_AI_TRACES_FAILED",
|
|
2569
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2570
|
+
category: error.ErrorCategory.USER
|
|
2571
|
+
},
|
|
2572
|
+
error$1
|
|
2573
|
+
);
|
|
2574
|
+
}
|
|
2575
|
+
}
|
|
2576
|
+
};
|
|
2204
2577
|
var StoreOperationsPG = class extends storage.StoreOperations {
|
|
2205
2578
|
client;
|
|
2206
2579
|
schemaName;
|
|
@@ -2219,6 +2592,45 @@ var StoreOperationsPG = class extends storage.StoreOperations {
|
|
|
2219
2592
|
);
|
|
2220
2593
|
return !!result;
|
|
2221
2594
|
}
|
|
2595
|
+
/**
|
|
2596
|
+
* Prepares values for insertion, handling JSONB columns by stringifying them
|
|
2597
|
+
*/
|
|
2598
|
+
prepareValuesForInsert(record, tableName) {
|
|
2599
|
+
return Object.entries(record).map(([key, value]) => {
|
|
2600
|
+
const schema = storage.TABLE_SCHEMAS[tableName];
|
|
2601
|
+
const columnSchema = schema?.[key];
|
|
2602
|
+
if (columnSchema?.type === "jsonb" && value !== null && typeof value === "object") {
|
|
2603
|
+
return JSON.stringify(value);
|
|
2604
|
+
}
|
|
2605
|
+
return value;
|
|
2606
|
+
});
|
|
2607
|
+
}
|
|
2608
|
+
/**
|
|
2609
|
+
* Adds timestamp Z columns to a record if timestamp columns exist
|
|
2610
|
+
*/
|
|
2611
|
+
addTimestampZColumns(record) {
|
|
2612
|
+
if (record.createdAt) {
|
|
2613
|
+
record.createdAtZ = record.createdAt;
|
|
2614
|
+
}
|
|
2615
|
+
if (record.created_at) {
|
|
2616
|
+
record.created_atZ = record.created_at;
|
|
2617
|
+
}
|
|
2618
|
+
if (record.updatedAt) {
|
|
2619
|
+
record.updatedAtZ = record.updatedAt;
|
|
2620
|
+
}
|
|
2621
|
+
}
|
|
2622
|
+
/**
|
|
2623
|
+
* Prepares a value for database operations, handling Date objects and JSON serialization
|
|
2624
|
+
*/
|
|
2625
|
+
prepareValue(value) {
|
|
2626
|
+
if (value instanceof Date) {
|
|
2627
|
+
return value.toISOString();
|
|
2628
|
+
} else if (typeof value === "object" && value !== null) {
|
|
2629
|
+
return JSON.stringify(value);
|
|
2630
|
+
} else {
|
|
2631
|
+
return value;
|
|
2632
|
+
}
|
|
2633
|
+
}
|
|
2222
2634
|
async setupSchema() {
|
|
2223
2635
|
if (!this.schemaName || this.schemaSetupComplete) {
|
|
2224
2636
|
return;
|
|
@@ -2262,18 +2674,10 @@ var StoreOperationsPG = class extends storage.StoreOperations {
|
|
|
2262
2674
|
}
|
|
2263
2675
|
async insert({ tableName, record }) {
|
|
2264
2676
|
try {
|
|
2265
|
-
|
|
2266
|
-
record.createdAtZ = record.createdAt;
|
|
2267
|
-
}
|
|
2268
|
-
if (record.created_at) {
|
|
2269
|
-
record.created_atZ = record.created_at;
|
|
2270
|
-
}
|
|
2271
|
-
if (record.updatedAt) {
|
|
2272
|
-
record.updatedAtZ = record.updatedAt;
|
|
2273
|
-
}
|
|
2677
|
+
this.addTimestampZColumns(record);
|
|
2274
2678
|
const schemaName = getSchemaName(this.schemaName);
|
|
2275
2679
|
const columns = Object.keys(record).map((col) => utils.parseSqlIdentifier(col, "column name"));
|
|
2276
|
-
const values =
|
|
2680
|
+
const values = this.prepareValuesForInsert(record, tableName);
|
|
2277
2681
|
const placeholders = values.map((_, i) => `$${i + 1}`).join(", ");
|
|
2278
2682
|
await this.client.none(
|
|
2279
2683
|
`INSERT INTO ${getTableName({ indexName: tableName, schemaName })} (${columns.map((c) => `"${c}"`).join(", ")}) VALUES (${placeholders})`,
|
|
@@ -2368,6 +2772,9 @@ var StoreOperationsPG = class extends storage.StoreOperations {
|
|
|
2368
2772
|
schema,
|
|
2369
2773
|
ifNotExists: timeZColumnNames
|
|
2370
2774
|
});
|
|
2775
|
+
if (tableName === storage.TABLE_AI_SPANS) {
|
|
2776
|
+
await this.setupTimestampTriggers(tableName);
|
|
2777
|
+
}
|
|
2371
2778
|
} catch (error$1) {
|
|
2372
2779
|
throw new error.MastraError(
|
|
2373
2780
|
{
|
|
@@ -2382,6 +2789,48 @@ var StoreOperationsPG = class extends storage.StoreOperations {
|
|
|
2382
2789
|
);
|
|
2383
2790
|
}
|
|
2384
2791
|
}
|
|
2792
|
+
/**
|
|
2793
|
+
* Set up timestamp triggers for a table to automatically manage createdAt/updatedAt
|
|
2794
|
+
*/
|
|
2795
|
+
async setupTimestampTriggers(tableName) {
|
|
2796
|
+
const fullTableName = getTableName({ indexName: tableName, schemaName: getSchemaName(this.schemaName) });
|
|
2797
|
+
try {
|
|
2798
|
+
const triggerSQL = `
|
|
2799
|
+
-- Create or replace the trigger function
|
|
2800
|
+
CREATE OR REPLACE FUNCTION trigger_set_timestamps()
|
|
2801
|
+
RETURNS TRIGGER AS $$
|
|
2802
|
+
BEGIN
|
|
2803
|
+
IF TG_OP = 'INSERT' THEN
|
|
2804
|
+
NEW."createdAt" = NOW();
|
|
2805
|
+
NEW."updatedAt" = NOW();
|
|
2806
|
+
NEW."createdAtZ" = NOW();
|
|
2807
|
+
NEW."updatedAtZ" = NOW();
|
|
2808
|
+
ELSIF TG_OP = 'UPDATE' THEN
|
|
2809
|
+
NEW."updatedAt" = NOW();
|
|
2810
|
+
NEW."updatedAtZ" = NOW();
|
|
2811
|
+
-- Prevent createdAt from being changed
|
|
2812
|
+
NEW."createdAt" = OLD."createdAt";
|
|
2813
|
+
NEW."createdAtZ" = OLD."createdAtZ";
|
|
2814
|
+
END IF;
|
|
2815
|
+
RETURN NEW;
|
|
2816
|
+
END;
|
|
2817
|
+
$$ LANGUAGE plpgsql;
|
|
2818
|
+
|
|
2819
|
+
-- Drop existing trigger if it exists
|
|
2820
|
+
DROP TRIGGER IF EXISTS ${tableName}_timestamps ON ${fullTableName};
|
|
2821
|
+
|
|
2822
|
+
-- Create the trigger
|
|
2823
|
+
CREATE TRIGGER ${tableName}_timestamps
|
|
2824
|
+
BEFORE INSERT OR UPDATE ON ${fullTableName}
|
|
2825
|
+
FOR EACH ROW
|
|
2826
|
+
EXECUTE FUNCTION trigger_set_timestamps();
|
|
2827
|
+
`;
|
|
2828
|
+
await this.client.none(triggerSQL);
|
|
2829
|
+
this.logger?.debug?.(`Set up timestamp triggers for table ${fullTableName}`);
|
|
2830
|
+
} catch (error) {
|
|
2831
|
+
this.logger?.warn?.(`Failed to set up timestamp triggers for ${fullTableName}:`, error);
|
|
2832
|
+
}
|
|
2833
|
+
}
|
|
2385
2834
|
/**
|
|
2386
2835
|
* Alters table schema to add columns if they don't exist
|
|
2387
2836
|
* @param tableName Name of the table
|
|
@@ -2524,8 +2973,8 @@ var StoreOperationsPG = class extends storage.StoreOperations {
|
|
|
2524
2973
|
schemaName: getSchemaName(this.schemaName)
|
|
2525
2974
|
});
|
|
2526
2975
|
const indexExists = await this.client.oneOrNone(
|
|
2527
|
-
`SELECT 1 FROM pg_indexes
|
|
2528
|
-
WHERE indexname = $1
|
|
2976
|
+
`SELECT 1 FROM pg_indexes
|
|
2977
|
+
WHERE indexname = $1
|
|
2529
2978
|
AND schemaname = $2`,
|
|
2530
2979
|
[name, schemaName]
|
|
2531
2980
|
);
|
|
@@ -2582,8 +3031,8 @@ var StoreOperationsPG = class extends storage.StoreOperations {
|
|
|
2582
3031
|
try {
|
|
2583
3032
|
const schemaName = this.schemaName || "public";
|
|
2584
3033
|
const indexExists = await this.client.oneOrNone(
|
|
2585
|
-
`SELECT 1 FROM pg_indexes
|
|
2586
|
-
WHERE indexname = $1
|
|
3034
|
+
`SELECT 1 FROM pg_indexes
|
|
3035
|
+
WHERE indexname = $1
|
|
2587
3036
|
AND schemaname = $2`,
|
|
2588
3037
|
[indexName, schemaName]
|
|
2589
3038
|
);
|
|
@@ -2616,7 +3065,7 @@ var StoreOperationsPG = class extends storage.StoreOperations {
|
|
|
2616
3065
|
let params;
|
|
2617
3066
|
if (tableName) {
|
|
2618
3067
|
query = `
|
|
2619
|
-
SELECT
|
|
3068
|
+
SELECT
|
|
2620
3069
|
i.indexname as name,
|
|
2621
3070
|
i.tablename as table,
|
|
2622
3071
|
i.indexdef as definition,
|
|
@@ -2627,14 +3076,14 @@ var StoreOperationsPG = class extends storage.StoreOperations {
|
|
|
2627
3076
|
JOIN pg_class c ON c.relname = i.indexname AND c.relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = i.schemaname)
|
|
2628
3077
|
JOIN pg_index ix ON ix.indexrelid = c.oid
|
|
2629
3078
|
JOIN pg_attribute a ON a.attrelid = ix.indrelid AND a.attnum = ANY(ix.indkey)
|
|
2630
|
-
WHERE i.schemaname = $1
|
|
3079
|
+
WHERE i.schemaname = $1
|
|
2631
3080
|
AND i.tablename = $2
|
|
2632
3081
|
GROUP BY i.indexname, i.tablename, i.indexdef, ix.indisunique, c.oid
|
|
2633
3082
|
`;
|
|
2634
3083
|
params = [schemaName, tableName];
|
|
2635
3084
|
} else {
|
|
2636
3085
|
query = `
|
|
2637
|
-
SELECT
|
|
3086
|
+
SELECT
|
|
2638
3087
|
i.indexname as name,
|
|
2639
3088
|
i.tablename as table,
|
|
2640
3089
|
i.indexdef as definition,
|
|
@@ -2713,6 +3162,33 @@ var StoreOperationsPG = class extends storage.StoreOperations {
|
|
|
2713
3162
|
name: `${schemaPrefix}mastra_evals_agent_name_created_at_idx`,
|
|
2714
3163
|
table: storage.TABLE_EVALS,
|
|
2715
3164
|
columns: ["agent_name", "created_at DESC"]
|
|
3165
|
+
},
|
|
3166
|
+
// Composite index for scores (filter + sort)
|
|
3167
|
+
{
|
|
3168
|
+
name: `${schemaPrefix}mastra_scores_trace_id_span_id_created_at_idx`,
|
|
3169
|
+
table: storage.TABLE_SCORERS,
|
|
3170
|
+
columns: ["trace_id", "span_id", "created_at DESC"]
|
|
3171
|
+
},
|
|
3172
|
+
// AI Spans indexes for optimal trace querying
|
|
3173
|
+
{
|
|
3174
|
+
name: `${schemaPrefix}mastra_ai_spans_traceid_startedat_idx`,
|
|
3175
|
+
table: storage.TABLE_AI_SPANS,
|
|
3176
|
+
columns: ["traceId", "startedAt DESC"]
|
|
3177
|
+
},
|
|
3178
|
+
{
|
|
3179
|
+
name: `${schemaPrefix}mastra_ai_spans_parentspanid_startedat_idx`,
|
|
3180
|
+
table: storage.TABLE_AI_SPANS,
|
|
3181
|
+
columns: ["parentSpanId", "startedAt DESC"]
|
|
3182
|
+
},
|
|
3183
|
+
{
|
|
3184
|
+
name: `${schemaPrefix}mastra_ai_spans_name_idx`,
|
|
3185
|
+
table: storage.TABLE_AI_SPANS,
|
|
3186
|
+
columns: ["name"]
|
|
3187
|
+
},
|
|
3188
|
+
{
|
|
3189
|
+
name: `${schemaPrefix}mastra_ai_spans_spantype_startedat_idx`,
|
|
3190
|
+
table: storage.TABLE_AI_SPANS,
|
|
3191
|
+
columns: ["spanType", "startedAt DESC"]
|
|
2716
3192
|
}
|
|
2717
3193
|
];
|
|
2718
3194
|
for (const indexOptions of indexes) {
|
|
@@ -2740,7 +3216,7 @@ var StoreOperationsPG = class extends storage.StoreOperations {
|
|
|
2740
3216
|
try {
|
|
2741
3217
|
const schemaName = this.schemaName || "public";
|
|
2742
3218
|
const query = `
|
|
2743
|
-
SELECT
|
|
3219
|
+
SELECT
|
|
2744
3220
|
i.indexname as name,
|
|
2745
3221
|
i.tablename as table,
|
|
2746
3222
|
i.indexdef as definition,
|
|
@@ -2757,7 +3233,7 @@ var StoreOperationsPG = class extends storage.StoreOperations {
|
|
|
2757
3233
|
JOIN pg_attribute a ON a.attrelid = ix.indrelid AND a.attnum = ANY(ix.indkey)
|
|
2758
3234
|
JOIN pg_am am ON c.relam = am.oid
|
|
2759
3235
|
LEFT JOIN pg_stat_user_indexes s ON s.indexrelname = i.indexname AND s.schemaname = i.schemaname
|
|
2760
|
-
WHERE i.schemaname = $1
|
|
3236
|
+
WHERE i.schemaname = $1
|
|
2761
3237
|
AND i.indexname = $2
|
|
2762
3238
|
GROUP BY i.indexname, i.tablename, i.indexdef, ix.indisunique, c.oid, am.amname, s.idx_scan, s.idx_tup_read, s.idx_tup_fetch
|
|
2763
3239
|
`;
|
|
@@ -2798,6 +3274,121 @@ var StoreOperationsPG = class extends storage.StoreOperations {
|
|
|
2798
3274
|
);
|
|
2799
3275
|
}
|
|
2800
3276
|
}
|
|
3277
|
+
/**
|
|
3278
|
+
* Update a single record in the database
|
|
3279
|
+
*/
|
|
3280
|
+
async update({
|
|
3281
|
+
tableName,
|
|
3282
|
+
keys,
|
|
3283
|
+
data
|
|
3284
|
+
}) {
|
|
3285
|
+
try {
|
|
3286
|
+
const setColumns = [];
|
|
3287
|
+
const setValues = [];
|
|
3288
|
+
let paramIndex = 1;
|
|
3289
|
+
Object.entries(data).forEach(([key, value]) => {
|
|
3290
|
+
const parsedKey = utils.parseSqlIdentifier(key, "column name");
|
|
3291
|
+
setColumns.push(`"${parsedKey}" = $${paramIndex++}`);
|
|
3292
|
+
setValues.push(this.prepareValue(value));
|
|
3293
|
+
});
|
|
3294
|
+
const whereConditions = [];
|
|
3295
|
+
const whereValues = [];
|
|
3296
|
+
Object.entries(keys).forEach(([key, value]) => {
|
|
3297
|
+
const parsedKey = utils.parseSqlIdentifier(key, "column name");
|
|
3298
|
+
whereConditions.push(`"${parsedKey}" = $${paramIndex++}`);
|
|
3299
|
+
whereValues.push(this.prepareValue(value));
|
|
3300
|
+
});
|
|
3301
|
+
const tableName_ = getTableName({
|
|
3302
|
+
indexName: tableName,
|
|
3303
|
+
schemaName: getSchemaName(this.schemaName)
|
|
3304
|
+
});
|
|
3305
|
+
const sql = `UPDATE ${tableName_} SET ${setColumns.join(", ")} WHERE ${whereConditions.join(" AND ")}`;
|
|
3306
|
+
const values = [...setValues, ...whereValues];
|
|
3307
|
+
await this.client.none(sql, values);
|
|
3308
|
+
} catch (error$1) {
|
|
3309
|
+
throw new error.MastraError(
|
|
3310
|
+
{
|
|
3311
|
+
id: "MASTRA_STORAGE_PG_STORE_UPDATE_FAILED",
|
|
3312
|
+
domain: error.ErrorDomain.STORAGE,
|
|
3313
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
3314
|
+
details: {
|
|
3315
|
+
tableName
|
|
3316
|
+
}
|
|
3317
|
+
},
|
|
3318
|
+
error$1
|
|
3319
|
+
);
|
|
3320
|
+
}
|
|
3321
|
+
}
|
|
3322
|
+
/**
|
|
3323
|
+
* Update multiple records in a single batch transaction
|
|
3324
|
+
*/
|
|
3325
|
+
async batchUpdate({
|
|
3326
|
+
tableName,
|
|
3327
|
+
updates
|
|
3328
|
+
}) {
|
|
3329
|
+
try {
|
|
3330
|
+
await this.client.query("BEGIN");
|
|
3331
|
+
for (const { keys, data } of updates) {
|
|
3332
|
+
await this.update({ tableName, keys, data });
|
|
3333
|
+
}
|
|
3334
|
+
await this.client.query("COMMIT");
|
|
3335
|
+
} catch (error$1) {
|
|
3336
|
+
await this.client.query("ROLLBACK");
|
|
3337
|
+
throw new error.MastraError(
|
|
3338
|
+
{
|
|
3339
|
+
id: "MASTRA_STORAGE_PG_STORE_BATCH_UPDATE_FAILED",
|
|
3340
|
+
domain: error.ErrorDomain.STORAGE,
|
|
3341
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
3342
|
+
details: {
|
|
3343
|
+
tableName,
|
|
3344
|
+
numberOfRecords: updates.length
|
|
3345
|
+
}
|
|
3346
|
+
},
|
|
3347
|
+
error$1
|
|
3348
|
+
);
|
|
3349
|
+
}
|
|
3350
|
+
}
|
|
3351
|
+
/**
|
|
3352
|
+
* Delete multiple records by keys
|
|
3353
|
+
*/
|
|
3354
|
+
async batchDelete({ tableName, keys }) {
|
|
3355
|
+
try {
|
|
3356
|
+
if (keys.length === 0) {
|
|
3357
|
+
return;
|
|
3358
|
+
}
|
|
3359
|
+
const tableName_ = getTableName({
|
|
3360
|
+
indexName: tableName,
|
|
3361
|
+
schemaName: getSchemaName(this.schemaName)
|
|
3362
|
+
});
|
|
3363
|
+
await this.client.tx(async (t) => {
|
|
3364
|
+
for (const keySet of keys) {
|
|
3365
|
+
const conditions = [];
|
|
3366
|
+
const values = [];
|
|
3367
|
+
let paramIndex = 1;
|
|
3368
|
+
Object.entries(keySet).forEach(([key, value]) => {
|
|
3369
|
+
const parsedKey = utils.parseSqlIdentifier(key, "column name");
|
|
3370
|
+
conditions.push(`"${parsedKey}" = $${paramIndex++}`);
|
|
3371
|
+
values.push(value);
|
|
3372
|
+
});
|
|
3373
|
+
const sql = `DELETE FROM ${tableName_} WHERE ${conditions.join(" AND ")}`;
|
|
3374
|
+
await t.none(sql, values);
|
|
3375
|
+
}
|
|
3376
|
+
});
|
|
3377
|
+
} catch (error$1) {
|
|
3378
|
+
throw new error.MastraError(
|
|
3379
|
+
{
|
|
3380
|
+
id: "MASTRA_STORAGE_PG_STORE_BATCH_DELETE_FAILED",
|
|
3381
|
+
domain: error.ErrorDomain.STORAGE,
|
|
3382
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
3383
|
+
details: {
|
|
3384
|
+
tableName,
|
|
3385
|
+
numberOfRecords: keys.length
|
|
3386
|
+
}
|
|
3387
|
+
},
|
|
3388
|
+
error$1
|
|
3389
|
+
);
|
|
3390
|
+
}
|
|
3391
|
+
}
|
|
2801
3392
|
};
|
|
2802
3393
|
function transformScoreRow(row) {
|
|
2803
3394
|
return {
|
|
@@ -2911,6 +3502,26 @@ var ScoresPG = class extends storage.ScoresStorage {
|
|
|
2911
3502
|
}
|
|
2912
3503
|
}
|
|
2913
3504
|
async saveScore(score) {
|
|
3505
|
+
let parsedScore;
|
|
3506
|
+
try {
|
|
3507
|
+
parsedScore = scores.saveScorePayloadSchema.parse(score);
|
|
3508
|
+
} catch (error$1) {
|
|
3509
|
+
throw new error.MastraError(
|
|
3510
|
+
{
|
|
3511
|
+
id: "MASTRA_STORAGE_PG_STORE_SAVE_SCORE_FAILED_INVALID_SCORE_PAYLOAD",
|
|
3512
|
+
domain: error.ErrorDomain.STORAGE,
|
|
3513
|
+
category: error.ErrorCategory.USER,
|
|
3514
|
+
details: {
|
|
3515
|
+
scorer: score.scorer.name,
|
|
3516
|
+
entityId: score.entityId,
|
|
3517
|
+
entityType: score.entityType,
|
|
3518
|
+
traceId: score.traceId || "",
|
|
3519
|
+
spanId: score.spanId || ""
|
|
3520
|
+
}
|
|
3521
|
+
},
|
|
3522
|
+
error$1
|
|
3523
|
+
);
|
|
3524
|
+
}
|
|
2914
3525
|
try {
|
|
2915
3526
|
const id = crypto.randomUUID();
|
|
2916
3527
|
const {
|
|
@@ -2924,7 +3535,7 @@ var ScoresPG = class extends storage.ScoresStorage {
|
|
|
2924
3535
|
runtimeContext,
|
|
2925
3536
|
entity,
|
|
2926
3537
|
...rest
|
|
2927
|
-
} =
|
|
3538
|
+
} = parsedScore;
|
|
2928
3539
|
await this.operations.insert({
|
|
2929
3540
|
tableName: storage.TABLE_SCORERS,
|
|
2930
3541
|
record: {
|
|
@@ -3045,6 +3656,44 @@ var ScoresPG = class extends storage.ScoresStorage {
|
|
|
3045
3656
|
);
|
|
3046
3657
|
}
|
|
3047
3658
|
}
|
|
3659
|
+
async getScoresBySpan({
|
|
3660
|
+
traceId,
|
|
3661
|
+
spanId,
|
|
3662
|
+
pagination
|
|
3663
|
+
}) {
|
|
3664
|
+
try {
|
|
3665
|
+
const tableName = getTableName({ indexName: storage.TABLE_SCORERS, schemaName: this.schema });
|
|
3666
|
+
const countSQLResult = await this.client.oneOrNone(
|
|
3667
|
+
`SELECT COUNT(*) as count FROM ${tableName} WHERE "traceId" = $1 AND "spanId" = $2`,
|
|
3668
|
+
[traceId, spanId]
|
|
3669
|
+
);
|
|
3670
|
+
const total = Number(countSQLResult?.count ?? 0);
|
|
3671
|
+
const result = await this.client.manyOrNone(
|
|
3672
|
+
`SELECT * FROM ${tableName} WHERE "traceId" = $1 AND "spanId" = $2 ORDER BY "createdAt" DESC LIMIT $3 OFFSET $4`,
|
|
3673
|
+
[traceId, spanId, pagination.perPage + 1, pagination.page * pagination.perPage]
|
|
3674
|
+
);
|
|
3675
|
+
const hasMore = result.length > pagination.perPage;
|
|
3676
|
+
const scores = result.slice(0, pagination.perPage).map((row) => transformScoreRow(row)) ?? [];
|
|
3677
|
+
return {
|
|
3678
|
+
scores,
|
|
3679
|
+
pagination: {
|
|
3680
|
+
total,
|
|
3681
|
+
page: pagination.page,
|
|
3682
|
+
perPage: pagination.perPage,
|
|
3683
|
+
hasMore
|
|
3684
|
+
}
|
|
3685
|
+
};
|
|
3686
|
+
} catch (error$1) {
|
|
3687
|
+
throw new error.MastraError(
|
|
3688
|
+
{
|
|
3689
|
+
id: "MASTRA_STORAGE_PG_STORE_GET_SCORES_BY_SPAN_FAILED",
|
|
3690
|
+
domain: error.ErrorDomain.STORAGE,
|
|
3691
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
3692
|
+
},
|
|
3693
|
+
error$1
|
|
3694
|
+
);
|
|
3695
|
+
}
|
|
3696
|
+
}
|
|
3048
3697
|
};
|
|
3049
3698
|
var TracesPG = class extends storage.TracesStorage {
|
|
3050
3699
|
client;
|
|
@@ -3440,7 +4089,8 @@ var PostgresStore = class extends storage.MastraStorage {
|
|
|
3440
4089
|
this.#config = {
|
|
3441
4090
|
connectionString: config.connectionString,
|
|
3442
4091
|
max: config.max,
|
|
3443
|
-
idleTimeoutMillis: config.idleTimeoutMillis
|
|
4092
|
+
idleTimeoutMillis: config.idleTimeoutMillis,
|
|
4093
|
+
ssl: config.ssl
|
|
3444
4094
|
};
|
|
3445
4095
|
} else if (isCloudSqlConfig(config)) {
|
|
3446
4096
|
this.#config = {
|
|
@@ -3460,11 +4110,9 @@ var PostgresStore = class extends storage.MastraStorage {
|
|
|
3460
4110
|
idleTimeoutMillis: config.idleTimeoutMillis
|
|
3461
4111
|
};
|
|
3462
4112
|
} else {
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
idleTimeoutMillis: config.idleTimeoutMillis
|
|
3467
|
-
};
|
|
4113
|
+
throw new Error(
|
|
4114
|
+
"PostgresStore: invalid config. Provide either {connectionString}, {host,port,database,user,password}, or a pg ClientConfig (e.g., Cloud SQL connector with `stream`)."
|
|
4115
|
+
);
|
|
3468
4116
|
}
|
|
3469
4117
|
this.stores = {};
|
|
3470
4118
|
} catch (e) {
|
|
@@ -3492,13 +4140,15 @@ var PostgresStore = class extends storage.MastraStorage {
|
|
|
3492
4140
|
const workflows = new WorkflowsPG({ client: this.#db, operations, schema: this.schema });
|
|
3493
4141
|
const legacyEvals = new LegacyEvalsPG({ client: this.#db, schema: this.schema });
|
|
3494
4142
|
const memory = new MemoryPG({ client: this.#db, schema: this.schema, operations });
|
|
4143
|
+
const observability = new ObservabilityPG({ client: this.#db, operations, schema: this.schema });
|
|
3495
4144
|
this.stores = {
|
|
3496
4145
|
operations,
|
|
3497
4146
|
scores,
|
|
3498
4147
|
traces,
|
|
3499
4148
|
workflows,
|
|
3500
4149
|
legacyEvals,
|
|
3501
|
-
memory
|
|
4150
|
+
memory,
|
|
4151
|
+
observability
|
|
3502
4152
|
};
|
|
3503
4153
|
await super.init();
|
|
3504
4154
|
try {
|
|
@@ -3537,8 +4187,9 @@ var PostgresStore = class extends storage.MastraStorage {
|
|
|
3537
4187
|
hasColumn: true,
|
|
3538
4188
|
createTable: true,
|
|
3539
4189
|
deleteMessages: true,
|
|
3540
|
-
aiTracing:
|
|
3541
|
-
indexManagement: true
|
|
4190
|
+
aiTracing: true,
|
|
4191
|
+
indexManagement: true,
|
|
4192
|
+
getScoresBySpan: true
|
|
3542
4193
|
};
|
|
3543
4194
|
}
|
|
3544
4195
|
/** @deprecated use getEvals instead */
|
|
@@ -3704,11 +4355,95 @@ var PostgresStore = class extends storage.MastraStorage {
|
|
|
3704
4355
|
async close() {
|
|
3705
4356
|
this.pgp.end();
|
|
3706
4357
|
}
|
|
4358
|
+
/**
|
|
4359
|
+
* AI Tracing / Observability
|
|
4360
|
+
*/
|
|
4361
|
+
async createAISpan(span) {
|
|
4362
|
+
if (!this.stores.observability) {
|
|
4363
|
+
throw new error.MastraError({
|
|
4364
|
+
id: "PG_STORE_OBSERVABILITY_NOT_INITIALIZED",
|
|
4365
|
+
domain: error.ErrorDomain.STORAGE,
|
|
4366
|
+
category: error.ErrorCategory.SYSTEM,
|
|
4367
|
+
text: "Observability storage is not initialized"
|
|
4368
|
+
});
|
|
4369
|
+
}
|
|
4370
|
+
return this.stores.observability.createAISpan(span);
|
|
4371
|
+
}
|
|
4372
|
+
async updateAISpan({
|
|
4373
|
+
spanId,
|
|
4374
|
+
traceId,
|
|
4375
|
+
updates
|
|
4376
|
+
}) {
|
|
4377
|
+
if (!this.stores.observability) {
|
|
4378
|
+
throw new error.MastraError({
|
|
4379
|
+
id: "PG_STORE_OBSERVABILITY_NOT_INITIALIZED",
|
|
4380
|
+
domain: error.ErrorDomain.STORAGE,
|
|
4381
|
+
category: error.ErrorCategory.SYSTEM,
|
|
4382
|
+
text: "Observability storage is not initialized"
|
|
4383
|
+
});
|
|
4384
|
+
}
|
|
4385
|
+
return this.stores.observability.updateAISpan({ spanId, traceId, updates });
|
|
4386
|
+
}
|
|
4387
|
+
async getAITrace(traceId) {
|
|
4388
|
+
if (!this.stores.observability) {
|
|
4389
|
+
throw new error.MastraError({
|
|
4390
|
+
id: "PG_STORE_OBSERVABILITY_NOT_INITIALIZED",
|
|
4391
|
+
domain: error.ErrorDomain.STORAGE,
|
|
4392
|
+
category: error.ErrorCategory.SYSTEM,
|
|
4393
|
+
text: "Observability storage is not initialized"
|
|
4394
|
+
});
|
|
4395
|
+
}
|
|
4396
|
+
return this.stores.observability.getAITrace(traceId);
|
|
4397
|
+
}
|
|
4398
|
+
async getAITracesPaginated(args) {
|
|
4399
|
+
if (!this.stores.observability) {
|
|
4400
|
+
throw new error.MastraError({
|
|
4401
|
+
id: "PG_STORE_OBSERVABILITY_NOT_INITIALIZED",
|
|
4402
|
+
domain: error.ErrorDomain.STORAGE,
|
|
4403
|
+
category: error.ErrorCategory.SYSTEM,
|
|
4404
|
+
text: "Observability storage is not initialized"
|
|
4405
|
+
});
|
|
4406
|
+
}
|
|
4407
|
+
return this.stores.observability.getAITracesPaginated(args);
|
|
4408
|
+
}
|
|
4409
|
+
async batchCreateAISpans(args) {
|
|
4410
|
+
if (!this.stores.observability) {
|
|
4411
|
+
throw new error.MastraError({
|
|
4412
|
+
id: "PG_STORE_OBSERVABILITY_NOT_INITIALIZED",
|
|
4413
|
+
domain: error.ErrorDomain.STORAGE,
|
|
4414
|
+
category: error.ErrorCategory.SYSTEM,
|
|
4415
|
+
text: "Observability storage is not initialized"
|
|
4416
|
+
});
|
|
4417
|
+
}
|
|
4418
|
+
return this.stores.observability.batchCreateAISpans(args);
|
|
4419
|
+
}
|
|
4420
|
+
async batchUpdateAISpans(args) {
|
|
4421
|
+
if (!this.stores.observability) {
|
|
4422
|
+
throw new error.MastraError({
|
|
4423
|
+
id: "PG_STORE_OBSERVABILITY_NOT_INITIALIZED",
|
|
4424
|
+
domain: error.ErrorDomain.STORAGE,
|
|
4425
|
+
category: error.ErrorCategory.SYSTEM,
|
|
4426
|
+
text: "Observability storage is not initialized"
|
|
4427
|
+
});
|
|
4428
|
+
}
|
|
4429
|
+
return this.stores.observability.batchUpdateAISpans(args);
|
|
4430
|
+
}
|
|
4431
|
+
async batchDeleteAITraces(args) {
|
|
4432
|
+
if (!this.stores.observability) {
|
|
4433
|
+
throw new error.MastraError({
|
|
4434
|
+
id: "PG_STORE_OBSERVABILITY_NOT_INITIALIZED",
|
|
4435
|
+
domain: error.ErrorDomain.STORAGE,
|
|
4436
|
+
category: error.ErrorCategory.SYSTEM,
|
|
4437
|
+
text: "Observability storage is not initialized"
|
|
4438
|
+
});
|
|
4439
|
+
}
|
|
4440
|
+
return this.stores.observability.batchDeleteAITraces(args);
|
|
4441
|
+
}
|
|
3707
4442
|
/**
|
|
3708
4443
|
* Scorers
|
|
3709
4444
|
*/
|
|
3710
|
-
async getScoreById({ id
|
|
3711
|
-
return this.stores.scores.getScoreById({ id
|
|
4445
|
+
async getScoreById({ id }) {
|
|
4446
|
+
return this.stores.scores.getScoreById({ id });
|
|
3712
4447
|
}
|
|
3713
4448
|
async getScoresByScorerId({
|
|
3714
4449
|
scorerId,
|
|
@@ -3719,26 +4454,33 @@ var PostgresStore = class extends storage.MastraStorage {
|
|
|
3719
4454
|
}) {
|
|
3720
4455
|
return this.stores.scores.getScoresByScorerId({ scorerId, pagination, entityId, entityType, source });
|
|
3721
4456
|
}
|
|
3722
|
-
async saveScore(
|
|
3723
|
-
return this.stores.scores.saveScore(
|
|
4457
|
+
async saveScore(score) {
|
|
4458
|
+
return this.stores.scores.saveScore(score);
|
|
3724
4459
|
}
|
|
3725
4460
|
async getScoresByRunId({
|
|
3726
|
-
runId
|
|
3727
|
-
pagination
|
|
4461
|
+
runId,
|
|
4462
|
+
pagination
|
|
3728
4463
|
}) {
|
|
3729
|
-
return this.stores.scores.getScoresByRunId({ runId
|
|
4464
|
+
return this.stores.scores.getScoresByRunId({ runId, pagination });
|
|
3730
4465
|
}
|
|
3731
4466
|
async getScoresByEntityId({
|
|
3732
|
-
entityId
|
|
3733
|
-
entityType
|
|
3734
|
-
pagination
|
|
4467
|
+
entityId,
|
|
4468
|
+
entityType,
|
|
4469
|
+
pagination
|
|
3735
4470
|
}) {
|
|
3736
4471
|
return this.stores.scores.getScoresByEntityId({
|
|
3737
|
-
entityId
|
|
3738
|
-
entityType
|
|
3739
|
-
pagination
|
|
4472
|
+
entityId,
|
|
4473
|
+
entityType,
|
|
4474
|
+
pagination
|
|
3740
4475
|
});
|
|
3741
4476
|
}
|
|
4477
|
+
async getScoresBySpan({
|
|
4478
|
+
traceId,
|
|
4479
|
+
spanId,
|
|
4480
|
+
pagination
|
|
4481
|
+
}) {
|
|
4482
|
+
return this.stores.scores.getScoresBySpan({ traceId, spanId, pagination });
|
|
4483
|
+
}
|
|
3742
4484
|
};
|
|
3743
4485
|
|
|
3744
4486
|
// src/vector/prompt.ts
|