@mastra/pg 1.34.0-alpha.0 → 1.34.0-alpha.1
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/README.md +1 -1
- package/dist/docs/SKILL.md +48 -0
- package/dist/docs/assets/SOURCE_MAP.json +6 -0
- package/dist/docs/references/docs-deployment-workers.md +404 -0
- package/dist/docs/references/docs-memory-semantic-recall.md +483 -0
- package/dist/docs/references/docs-memory-working-memory.md +450 -0
- package/dist/docs/references/docs-storage.md +224 -0
- package/dist/docs/references/integrations-databases-clickhouse-managed-postgres.md +82 -0
- package/dist/docs/references/integrations-databases-dynamodb.md +286 -0
- package/dist/docs/references/integrations-databases-neon.md +222 -0
- package/dist/docs/references/integrations-databases-postgresql.md +592 -0
- package/dist/docs/references/integrations-vectors-pg.md +451 -0
- package/dist/docs/references/reference-memory-memory-class.md +237 -0
- package/dist/docs/references/reference-processors-message-history-processor.md +89 -0
- package/dist/docs/references/reference-processors-semantic-recall-processor.md +119 -0
- package/dist/docs/references/reference-processors-working-memory-processor.md +154 -0
- package/dist/docs/references/reference-rag-chunking-and-embedding.md +184 -0
- package/dist/docs/references/reference-rag-metadata-filters.md +238 -0
- package/dist/docs/references/reference-rag-overview.md +76 -0
- package/dist/docs/references/reference-rag-retrieval.md +668 -0
- package/dist/docs/references/reference-rag-vector-databases.md +808 -0
- package/dist/docs/references/reference-storage-composite.md +433 -0
- package/dist/docs/references/reference-storage-retention.md +310 -0
- package/dist/docs/references/reference-tools-vector-query-tool.md +500 -0
- package/dist/index.cjs +152 -48
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +152 -48
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/background-tasks/index.d.ts +1 -0
- package/dist/storage/domains/background-tasks/index.d.ts.map +1 -1
- package/dist/storage/domains/experiments/index.d.ts +3 -3
- package/dist/storage/domains/experiments/index.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/index.d.ts +1 -1
- package/dist/storage/domains/observability/v-next/index.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/preview-compat.d.ts +3 -0
- package/dist/storage/domains/observability/v-next/preview-compat.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/span-query.d.ts +3 -0
- package/dist/storage/domains/observability/v-next/span-query.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/trace-aggregate.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/trace-query.d.ts +7 -0
- package/dist/storage/domains/observability/v-next/trace-query.d.ts.map +1 -1
- package/dist/storage/test-utils.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -5262,6 +5262,7 @@ function rowToTask(row) {
|
|
|
5262
5262
|
const suspendedAt = row.suspendedAtZ || row.suspendedAt;
|
|
5263
5263
|
const completedAt = row.completedAtZ || row.completedAt;
|
|
5264
5264
|
const leaseExpiresAt = row.leaseExpiresAtZ || row.leaseExpiresAt;
|
|
5265
|
+
const expiresAt = row.expiresAt != null ? row.expiresAtZ || row.expiresAt : void 0;
|
|
5265
5266
|
return {
|
|
5266
5267
|
id: row.id,
|
|
5267
5268
|
status: row.status,
|
|
@@ -5283,10 +5284,13 @@ function rowToTask(row) {
|
|
|
5283
5284
|
suspendedAt: suspendedAt ? suspendedAt instanceof Date ? suspendedAt : new Date(suspendedAt) : void 0,
|
|
5284
5285
|
completedAt: completedAt ? completedAt instanceof Date ? completedAt : new Date(completedAt) : void 0,
|
|
5285
5286
|
ownerId: row.ownerId ?? void 0,
|
|
5286
|
-
leaseExpiresAt: leaseExpiresAt ? leaseExpiresAt instanceof Date ? leaseExpiresAt : new Date(leaseExpiresAt) : void 0
|
|
5287
|
+
leaseExpiresAt: leaseExpiresAt ? leaseExpiresAt instanceof Date ? leaseExpiresAt : new Date(leaseExpiresAt) : void 0,
|
|
5288
|
+
expiresAt: expiresAt ? expiresAt instanceof Date ? expiresAt : new Date(expiresAt) : void 0,
|
|
5289
|
+
metadata: parseJson$2(row.metadata)
|
|
5287
5290
|
};
|
|
5288
5291
|
}
|
|
5289
5292
|
var BackgroundTasksPG = class BackgroundTasksPG extends BackgroundTasksStorage {
|
|
5293
|
+
supportsTaskExpiry = true;
|
|
5290
5294
|
#db;
|
|
5291
5295
|
#schema;
|
|
5292
5296
|
#skipDefaultIndexes;
|
|
@@ -5327,7 +5331,9 @@ var BackgroundTasksPG = class BackgroundTasksPG extends BackgroundTasksStorage {
|
|
|
5327
5331
|
"suspend_payload",
|
|
5328
5332
|
"suspendedAt",
|
|
5329
5333
|
"ownerId",
|
|
5330
|
-
"leaseExpiresAt"
|
|
5334
|
+
"leaseExpiresAt",
|
|
5335
|
+
"expiresAt",
|
|
5336
|
+
"metadata"
|
|
5331
5337
|
]
|
|
5332
5338
|
});
|
|
5333
5339
|
await this.createDefaultIndexes();
|
|
@@ -5461,7 +5467,10 @@ var BackgroundTasksPG = class BackgroundTasksPG extends BackgroundTasksStorage {
|
|
|
5461
5467
|
completedAtZ: task.completedAt?.toISOString() ?? null,
|
|
5462
5468
|
ownerId: task.ownerId ?? null,
|
|
5463
5469
|
leaseExpiresAt: task.leaseExpiresAt?.toISOString() ?? null,
|
|
5464
|
-
leaseExpiresAtZ: task.leaseExpiresAt?.toISOString() ?? null
|
|
5470
|
+
leaseExpiresAtZ: task.leaseExpiresAt?.toISOString() ?? null,
|
|
5471
|
+
expiresAt: task.expiresAt?.toISOString() ?? null,
|
|
5472
|
+
expiresAtZ: task.expiresAt?.toISOString() ?? null,
|
|
5473
|
+
metadata: serializeJson(task.metadata)
|
|
5465
5474
|
}
|
|
5466
5475
|
});
|
|
5467
5476
|
}
|
|
@@ -5517,6 +5526,16 @@ var BackgroundTasksPG = class BackgroundTasksPG extends BackgroundTasksStorage {
|
|
|
5517
5526
|
const val = update.leaseExpiresAt?.toISOString() ?? null;
|
|
5518
5527
|
params.push(val, val);
|
|
5519
5528
|
}
|
|
5529
|
+
if ("expiresAt" in update) {
|
|
5530
|
+
setClauses.push(`"expiresAt" = $${paramIdx++}`);
|
|
5531
|
+
setClauses.push(`"expiresAtZ" = $${paramIdx++}`);
|
|
5532
|
+
const val = update.expiresAt?.toISOString() ?? null;
|
|
5533
|
+
params.push(val, val);
|
|
5534
|
+
}
|
|
5535
|
+
if ("metadata" in update) {
|
|
5536
|
+
setClauses.push(`"metadata" = $${paramIdx++}`);
|
|
5537
|
+
params.push(serializeJson(update.metadata));
|
|
5538
|
+
}
|
|
5520
5539
|
if (setClauses.length === 0) return false;
|
|
5521
5540
|
const table = getTableName$4(getSchemaName$4(this.#schema));
|
|
5522
5541
|
params.push(taskId);
|
|
@@ -5539,6 +5558,13 @@ var BackgroundTasksPG = class BackgroundTasksPG extends BackgroundTasksStorage {
|
|
|
5539
5558
|
params.push(options.expectedLeaseExpiresAt.toISOString());
|
|
5540
5559
|
}
|
|
5541
5560
|
}
|
|
5561
|
+
if (options?.expectedSuspendedAt !== void 0) {
|
|
5562
|
+
if (options.expectedSuspendedAt === null) where += ` AND "suspendedAtZ" IS NULL`;
|
|
5563
|
+
else {
|
|
5564
|
+
where += ` AND "suspendedAtZ" = $${paramIdx++}`;
|
|
5565
|
+
params.push(options.expectedSuspendedAt.toISOString());
|
|
5566
|
+
}
|
|
5567
|
+
}
|
|
5542
5568
|
return ((await this.#db.client.query(`UPDATE ${table} SET ${setClauses.join(", ")} WHERE ${where}`, params)).rowCount ?? 0) > 0;
|
|
5543
5569
|
}
|
|
5544
5570
|
async getTask(taskId) {
|
|
@@ -5581,7 +5607,9 @@ var BackgroundTasksPG = class BackgroundTasksPG extends BackgroundTasksStorage {
|
|
|
5581
5607
|
conditions.push(`"tool_call_id" = $${paramIdx++}`);
|
|
5582
5608
|
params.push(filter.toolCallId);
|
|
5583
5609
|
}
|
|
5584
|
-
const dateCol = filter.dateFilterBy === "startedAt" ? "\"startedAt\"" : filter.dateFilterBy === "suspendedAt" ? "\"suspendedAt\"" : filter.dateFilterBy === "completedAt" ? "\"completedAt\"" : "\"createdAt\"";
|
|
5610
|
+
const dateCol = filter.dateFilterBy === "startedAt" ? "\"startedAt\"" : filter.dateFilterBy === "suspendedAt" ? "\"suspendedAt\"" : filter.dateFilterBy === "completedAt" ? "\"completedAt\"" : filter.dateFilterBy === "expiresAt" ? "\"expiresAtZ\"" : "\"createdAt\"";
|
|
5611
|
+
if (filter.hasExpiresAt !== void 0) conditions.push(filter.hasExpiresAt ? "\"expiresAt\" IS NOT NULL" : "\"expiresAt\" IS NULL");
|
|
5612
|
+
if (filter.dateFilterBy === "expiresAt" && (filter.fromDate || filter.toDate)) conditions.push("\"expiresAt\" IS NOT NULL");
|
|
5585
5613
|
if (filter.fromDate) {
|
|
5586
5614
|
conditions.push(`${dateCol} >= $${paramIdx++}`);
|
|
5587
5615
|
params.push(filter.fromDate.toISOString());
|
|
@@ -5622,7 +5650,9 @@ var BackgroundTasksPG = class BackgroundTasksPG extends BackgroundTasksStorage {
|
|
|
5622
5650
|
conditions.push(`"status" IN (${placeholders.join(", ")})`);
|
|
5623
5651
|
params.push(...statuses);
|
|
5624
5652
|
}
|
|
5625
|
-
const dateCol = filter.dateFilterBy === "startedAt" ? "\"startedAt\"" : filter.dateFilterBy === "suspendedAt" ? "\"suspendedAt\"" : filter.dateFilterBy === "completedAt" ? "\"completedAt\"" : "\"createdAt\"";
|
|
5653
|
+
const dateCol = filter.dateFilterBy === "startedAt" ? "\"startedAt\"" : filter.dateFilterBy === "suspendedAt" ? "\"suspendedAt\"" : filter.dateFilterBy === "completedAt" ? "\"completedAt\"" : filter.dateFilterBy === "expiresAt" ? "\"expiresAtZ\"" : "\"createdAt\"";
|
|
5654
|
+
if (filter.hasExpiresAt !== void 0) conditions.push(filter.hasExpiresAt ? "\"expiresAt\" IS NOT NULL" : "\"expiresAt\" IS NULL");
|
|
5655
|
+
if (filter.dateFilterBy === "expiresAt" && (filter.fromDate || filter.toDate)) conditions.push("\"expiresAt\" IS NOT NULL");
|
|
5626
5656
|
if (filter.fromDate) {
|
|
5627
5657
|
conditions.push(`${dateCol} >= $${paramIdx++}`);
|
|
5628
5658
|
params.push(filter.fromDate.toISOString());
|
|
@@ -7238,6 +7268,19 @@ var DatasetsPG = class DatasetsPG extends DatasetsStorage {
|
|
|
7238
7268
|
};
|
|
7239
7269
|
// src/storage/domains/experiments/index.ts
|
|
7240
7270
|
const DEFAULT_PRUNE_BATCH_SIZE = 1e3;
|
|
7271
|
+
/**
|
|
7272
|
+
* Column list for reading experiment rows. Each `timestamp` column comes back
|
|
7273
|
+
* twice: as itself, and as its `*Z` mirror derived in the query with
|
|
7274
|
+
* `AT TIME ZONE 'UTC'`. A plain `timestamp` otherwise round-trips through the
|
|
7275
|
+
* session timezone, and reading the stored `*Z` column instead would return the
|
|
7276
|
+
* insert time for rows written before the mirrors were filled in. Deriving it
|
|
7277
|
+
* here makes legacy rows read correctly with no backfill to run at startup.
|
|
7278
|
+
*/
|
|
7279
|
+
function selectWithMirrors(schema) {
|
|
7280
|
+
return Object.entries(schema).flatMap(([name, definition]) => definition.type === "timestamp" ? [`"${name}"`, `"${name}" AT TIME ZONE 'UTC' AS "${name}Z"`] : [`"${name}"`]).join(", ");
|
|
7281
|
+
}
|
|
7282
|
+
const EXPERIMENT_COLUMNS = selectWithMirrors(EXPERIMENTS_SCHEMA);
|
|
7283
|
+
const EXPERIMENT_RESULT_COLUMNS = selectWithMirrors(EXPERIMENT_RESULTS_SCHEMA);
|
|
7241
7284
|
var ExperimentsPG = class ExperimentsPG extends ExperimentsStorage {
|
|
7242
7285
|
#db;
|
|
7243
7286
|
#schema;
|
|
@@ -7246,9 +7289,9 @@ var ExperimentsPG = class ExperimentsPG extends ExperimentsStorage {
|
|
|
7246
7289
|
static MANAGED_TABLES = [TABLE_EXPERIMENTS, TABLE_EXPERIMENT_RESULTS];
|
|
7247
7290
|
/**
|
|
7248
7291
|
* Experiments prune as whole units: an aged experiment and its result rows go
|
|
7249
|
-
* together, mirroring `deleteExperiment`. Anchored on `completedAt`
|
|
7250
|
-
* `completedAtZ` mirror
|
|
7251
|
-
*
|
|
7292
|
+
* together, mirroring `deleteExperiment`. Anchored on `completedAt` rather
|
|
7293
|
+
* than its `completedAtZ` mirror: both are written together, but
|
|
7294
|
+
* `completedAt` is the column the retention index covers. `completedAt` is
|
|
7252
7295
|
* written as a UTC ISO string and stays NULL while running, so
|
|
7253
7296
|
* `completedAt < cutoff` is false for in-flight experiments.
|
|
7254
7297
|
*/
|
|
@@ -7568,7 +7611,11 @@ var ExperimentsPG = class ExperimentsPG extends ExperimentsStorage {
|
|
|
7568
7611
|
startedAt: null,
|
|
7569
7612
|
completedAt: null,
|
|
7570
7613
|
createdAt: nowIso,
|
|
7571
|
-
updatedAt: nowIso
|
|
7614
|
+
updatedAt: nowIso,
|
|
7615
|
+
startedAtZ: null,
|
|
7616
|
+
completedAtZ: null,
|
|
7617
|
+
createdAtZ: nowIso,
|
|
7618
|
+
updatedAtZ: nowIso
|
|
7572
7619
|
}
|
|
7573
7620
|
});
|
|
7574
7621
|
return {
|
|
@@ -7657,12 +7704,14 @@ var ExperimentsPG = class ExperimentsPG extends ExperimentsStorage {
|
|
|
7657
7704
|
values.push(input.skippedCount);
|
|
7658
7705
|
}
|
|
7659
7706
|
if (input.startedAt !== void 0) {
|
|
7660
|
-
|
|
7661
|
-
|
|
7707
|
+
const iso = input.startedAt?.toISOString() ?? null;
|
|
7708
|
+
setClauses.push(`"startedAt" = $${paramIndex++}`, `"startedAtZ" = $${paramIndex++}`);
|
|
7709
|
+
values.push(iso, iso);
|
|
7662
7710
|
}
|
|
7663
7711
|
if (input.completedAt !== void 0) {
|
|
7664
|
-
|
|
7665
|
-
|
|
7712
|
+
const iso = input.completedAt?.toISOString() ?? null;
|
|
7713
|
+
setClauses.push(`"completedAt" = $${paramIndex++}`, `"completedAtZ" = $${paramIndex++}`);
|
|
7714
|
+
values.push(iso, iso);
|
|
7666
7715
|
}
|
|
7667
7716
|
values.push(input.id);
|
|
7668
7717
|
await this.#db.client.none(`UPDATE ${tableName} SET ${setClauses.join(", ")} WHERE "id" = $${paramIndex}`, values);
|
|
@@ -7691,7 +7740,7 @@ var ExperimentsPG = class ExperimentsPG extends ExperimentsStorage {
|
|
|
7691
7740
|
});
|
|
7692
7741
|
const { conditions, params } = tenancyWhere(filters, 2);
|
|
7693
7742
|
const whereSql = ["\"id\" = $1", ...conditions].join(" AND ");
|
|
7694
|
-
const result = await client.oneOrNone(`SELECT
|
|
7743
|
+
const result = await client.oneOrNone(`SELECT ${EXPERIMENT_COLUMNS} FROM ${tableName} WHERE ${whereSql}`, [id, ...params]);
|
|
7695
7744
|
return result ? this.transformExperimentRow(result) : null;
|
|
7696
7745
|
} catch (error) {
|
|
7697
7746
|
throw new MastraError({
|
|
@@ -7778,7 +7827,7 @@ var ExperimentsPG = class ExperimentsPG extends ExperimentsStorage {
|
|
|
7778
7827
|
const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
|
|
7779
7828
|
const limitValue = perPageInput === false ? total : perPage;
|
|
7780
7829
|
return {
|
|
7781
|
-
experiments: (await this.#db.readClient.manyOrNone(`SELECT
|
|
7830
|
+
experiments: (await this.#db.readClient.manyOrNone(`SELECT ${EXPERIMENT_COLUMNS} FROM ${tableName} ${whereClause} ORDER BY "${orderBy.field}" ${orderBy.direction}, "id" ASC LIMIT $${paramIndex} OFFSET $${paramIndex + 1}`, [
|
|
7782
7831
|
...queryParams,
|
|
7783
7832
|
limitValue,
|
|
7784
7833
|
offset
|
|
@@ -7856,9 +7905,11 @@ var ExperimentsPG = class ExperimentsPG extends ExperimentsStorage {
|
|
|
7856
7905
|
return t.one(`INSERT INTO ${resultsTable} (
|
|
7857
7906
|
"id", "experimentId", "itemId", "itemDatasetVersion", "organizationId", "projectId",
|
|
7858
7907
|
"input", "output", "groundTruth", "metadata", "error", "startedAt", "completedAt",
|
|
7859
|
-
"retryCount", "attempt", "traceId", "status", "tags", "toolMockReport", "createdAt"
|
|
7860
|
-
|
|
7861
|
-
|
|
7908
|
+
"retryCount", "attempt", "traceId", "status", "tags", "toolMockReport", "createdAt",
|
|
7909
|
+
"startedAtZ", "completedAtZ", "createdAtZ"
|
|
7910
|
+
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20,
|
|
7911
|
+
$21, $22, $23)
|
|
7912
|
+
RETURNING ${EXPERIMENT_RESULT_COLUMNS}`, [
|
|
7862
7913
|
id,
|
|
7863
7914
|
input.experimentId,
|
|
7864
7915
|
input.itemId,
|
|
@@ -7878,6 +7929,9 @@ var ExperimentsPG = class ExperimentsPG extends ExperimentsStorage {
|
|
|
7878
7929
|
input.status ?? null,
|
|
7879
7930
|
purgeMetadata || input.tags == null ? null : toPgJson(input.tags),
|
|
7880
7931
|
purgeMetadata || input.toolMockReport == null ? null : toPgJson(input.toolMockReport),
|
|
7932
|
+
nowIso,
|
|
7933
|
+
input.startedAt.toISOString(),
|
|
7934
|
+
input.completedAt.toISOString(),
|
|
7881
7935
|
nowIso
|
|
7882
7936
|
]);
|
|
7883
7937
|
});
|
|
@@ -7904,6 +7958,7 @@ var ExperimentsPG = class ExperimentsPG extends ExperimentsStorage {
|
|
|
7904
7958
|
const row = await this.#db.client.tx(async (t) => {
|
|
7905
7959
|
const owner = await t.oneOrNone(`SELECT "datasetId" FROM ${experimentsTable} WHERE "id" = $1`, [input.experimentId]);
|
|
7906
7960
|
const purgeMetadata = await this.#resolvePurgeMetadata(t, owner?.datasetId, input.itemId);
|
|
7961
|
+
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
7907
7962
|
const existing = await t.oneOrNone(`SELECT "id" FROM ${tableName} WHERE "experimentId" = $1 AND "itemId" = $2 AND COALESCE("attempt", 0) = $3 FOR UPDATE`, [
|
|
7908
7963
|
input.experimentId,
|
|
7909
7964
|
input.itemId,
|
|
@@ -7914,9 +7969,11 @@ var ExperimentsPG = class ExperimentsPG extends ExperimentsStorage {
|
|
|
7914
7969
|
return t.one(`INSERT INTO ${tableName} (
|
|
7915
7970
|
"id", "experimentId", "itemId", "itemDatasetVersion", "organizationId", "projectId",
|
|
7916
7971
|
"input", "output", "groundTruth", "metadata", "error", "startedAt", "completedAt",
|
|
7917
|
-
"retryCount", "attempt", "traceId", "status", "tags", "toolMockReport", "createdAt"
|
|
7918
|
-
|
|
7919
|
-
|
|
7972
|
+
"retryCount", "attempt", "traceId", "status", "tags", "toolMockReport", "createdAt",
|
|
7973
|
+
"startedAtZ", "completedAtZ", "createdAtZ"
|
|
7974
|
+
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20,
|
|
7975
|
+
$21, $22, $23)
|
|
7976
|
+
RETURNING ${EXPERIMENT_RESULT_COLUMNS}`, [
|
|
7920
7977
|
id,
|
|
7921
7978
|
input.experimentId,
|
|
7922
7979
|
input.itemId,
|
|
@@ -7936,15 +7993,19 @@ var ExperimentsPG = class ExperimentsPG extends ExperimentsStorage {
|
|
|
7936
7993
|
input.status ?? null,
|
|
7937
7994
|
purgeMetadata || input.tags == null ? null : toPgJson(input.tags),
|
|
7938
7995
|
purgeMetadata || input.toolMockReport == null ? null : toPgJson(input.toolMockReport),
|
|
7939
|
-
|
|
7996
|
+
nowIso,
|
|
7997
|
+
input.startedAt.toISOString(),
|
|
7998
|
+
input.completedAt.toISOString(),
|
|
7999
|
+
nowIso
|
|
7940
8000
|
]);
|
|
7941
8001
|
}
|
|
7942
8002
|
return t.one(`UPDATE ${tableName} SET
|
|
7943
8003
|
"itemDatasetVersion" = $2, "organizationId" = $3, "projectId" = $4,
|
|
7944
8004
|
"input" = $5, "output" = $6, "groundTruth" = $7, "metadata" = $8, "error" = $9,
|
|
7945
8005
|
"startedAt" = $10, "completedAt" = $11, "retryCount" = $12, "attempt" = $13,
|
|
7946
|
-
"traceId" = $14, "status" = $15, "tags" = $16, "toolMockReport" = $17
|
|
7947
|
-
|
|
8006
|
+
"traceId" = $14, "status" = $15, "tags" = $16, "toolMockReport" = $17,
|
|
8007
|
+
"startedAtZ" = $18, "completedAtZ" = $19
|
|
8008
|
+
WHERE "id" = $1 RETURNING ${EXPERIMENT_RESULT_COLUMNS}`, [
|
|
7948
8009
|
existing.id,
|
|
7949
8010
|
input.itemDatasetVersion ?? null,
|
|
7950
8011
|
input.organizationId ?? null,
|
|
@@ -7961,7 +8022,9 @@ var ExperimentsPG = class ExperimentsPG extends ExperimentsStorage {
|
|
|
7961
8022
|
input.traceId ?? null,
|
|
7962
8023
|
input.status ?? null,
|
|
7963
8024
|
purgeMetadata || input.tags == null ? null : toPgJson(input.tags),
|
|
7964
|
-
purgeMetadata || input.toolMockReport == null ? null : toPgJson(input.toolMockReport)
|
|
8025
|
+
purgeMetadata || input.toolMockReport == null ? null : toPgJson(input.toolMockReport),
|
|
8026
|
+
input.startedAt.toISOString(),
|
|
8027
|
+
input.completedAt.toISOString()
|
|
7965
8028
|
]);
|
|
7966
8029
|
});
|
|
7967
8030
|
return this.transformExperimentResultRow(row);
|
|
@@ -7995,7 +8058,7 @@ var ExperimentsPG = class ExperimentsPG extends ExperimentsStorage {
|
|
|
7995
8058
|
"tags" = CASE WHEN $4 THEN NULL WHEN $5 THEN $6::jsonb ELSE "tags" END,
|
|
7996
8059
|
"comment" = CASE WHEN $4 THEN NULL WHEN $7 THEN $8 ELSE "comment" END
|
|
7997
8060
|
WHERE "id" = $1${input.experimentId !== void 0 ? " AND \"experimentId\" = $9" : ""}
|
|
7998
|
-
RETURNING
|
|
8061
|
+
RETURNING ${EXPERIMENT_RESULT_COLUMNS}`, [
|
|
7999
8062
|
input.id,
|
|
8000
8063
|
input.status !== void 0,
|
|
8001
8064
|
input.status ?? null,
|
|
@@ -8038,7 +8101,7 @@ var ExperimentsPG = class ExperimentsPG extends ExperimentsStorage {
|
|
|
8038
8101
|
});
|
|
8039
8102
|
const { conditions, params } = tenancyWhere(filters, 2);
|
|
8040
8103
|
const whereSql = ["\"id\" = $1", ...conditions].join(" AND ");
|
|
8041
|
-
const result = await client.oneOrNone(`SELECT
|
|
8104
|
+
const result = await client.oneOrNone(`SELECT ${EXPERIMENT_RESULT_COLUMNS} FROM ${tableName} WHERE ${whereSql}`, [id, ...params]);
|
|
8042
8105
|
return result ? this.transformExperimentResultRow(result) : null;
|
|
8043
8106
|
} catch (error) {
|
|
8044
8107
|
throw new MastraError({
|
|
@@ -8101,7 +8164,7 @@ var ExperimentsPG = class ExperimentsPG extends ExperimentsStorage {
|
|
|
8101
8164
|
const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
|
|
8102
8165
|
const limitValue = perPageInput === false ? total : perPage;
|
|
8103
8166
|
return {
|
|
8104
|
-
results: (await this.#db.readClient.manyOrNone(`SELECT
|
|
8167
|
+
results: (await this.#db.readClient.manyOrNone(`SELECT ${EXPERIMENT_RESULT_COLUMNS} FROM ${tableName} ${whereClause} ORDER BY "${orderBy.field}" ${orderBy.direction}, "id" ASC LIMIT $${paramIndex} OFFSET $${paramIndex + 1}`, [
|
|
8105
8168
|
...queryParams,
|
|
8106
8169
|
limitValue,
|
|
8107
8170
|
offset
|
|
@@ -19520,6 +19583,13 @@ const timeToFirstChunkSortSupported = coreStorage.TRACE_QUERY_ORDER_FIELDS?.incl
|
|
|
19520
19583
|
/** Same rule for time to first token: returned and sorted only when core knows the field. */
|
|
19521
19584
|
const timeToFirstTokenSupported = "timeToFirstTokenMs" in coreStorage.TRACE_QUERY_FIELD_REGISTRY.trace;
|
|
19522
19585
|
const timeToFirstTokenSortSupported = coreStorage.TRACE_QUERY_ORDER_FIELDS?.includes("timeToFirstTokenMs") === true;
|
|
19586
|
+
/**
|
|
19587
|
+
* Outcome fields follow the same rule: core before them rejects their predicates and strict rows,
|
|
19588
|
+
* so they are only returned and declared when core knows them.
|
|
19589
|
+
*/
|
|
19590
|
+
const spanQueryOutcomeFieldsSupported = "outcome" in (coreStorage.SPAN_QUERY_FIELD_REGISTRY ?? {});
|
|
19591
|
+
const traceQueryOutcomeFieldsSupported = "outcome" in (coreStorage.TRACE_QUERY_FIELD_REGISTRY?.trace ?? {});
|
|
19592
|
+
const outcomeFeatures = [...spanQueryOutcomeFieldsSupported ? ["span-query-outcome-fields"] : [], ...traceQueryOutcomeFieldsSupported ? ["trace-query-outcome-fields"] : []];
|
|
19523
19593
|
const timingFeatures = [
|
|
19524
19594
|
...timeToFirstChunkSupported ? ["trace-query-time-to-first-chunk"] : [],
|
|
19525
19595
|
...timeToFirstChunkSortSupported ? ["trace-query-time-to-first-chunk-sort"] : [],
|
|
@@ -19566,6 +19636,8 @@ const TRACE_FIELDS = {
|
|
|
19566
19636
|
spanType: "r.\"spanType\"",
|
|
19567
19637
|
environment: "r.\"environment\"",
|
|
19568
19638
|
status: TRACE_STATUS_SQL,
|
|
19639
|
+
outcome: "r.\"outcome\"",
|
|
19640
|
+
stopReason: "r.\"stopReason\"",
|
|
19569
19641
|
tags: "r.\"tags\""
|
|
19570
19642
|
};
|
|
19571
19643
|
const SPAN_FIELDS = {
|
|
@@ -19579,6 +19651,8 @@ const SPAN_FIELDS = {
|
|
|
19579
19651
|
timeToFirstChunkMs: "s.\"timeToFirstChunkMs\"",
|
|
19580
19652
|
timeToFirstTokenMs: "s.\"timeToFirstTokenMs\"",
|
|
19581
19653
|
status: "s.\"status\"",
|
|
19654
|
+
outcome: "s.\"outcome\"",
|
|
19655
|
+
stopReason: "s.\"stopReason\"",
|
|
19582
19656
|
error: "s.\"error\"",
|
|
19583
19657
|
entityType: "s.\"entityType\"",
|
|
19584
19658
|
entityId: "s.\"entityId\"",
|
|
@@ -19652,7 +19726,10 @@ const TRACE_SELECT = `
|
|
|
19652
19726
|
r."entityName" AS "entityName",
|
|
19653
19727
|
r."entityType" AS "entityType",
|
|
19654
19728
|
r."environment" AS "environment",
|
|
19655
|
-
${TRACE_STATUS_SQL} AS "status"
|
|
19729
|
+
${TRACE_STATUS_SQL} AS "status",
|
|
19730
|
+
r."outcome" AS "outcome",
|
|
19731
|
+
r."stopReason" AS "stopReason",
|
|
19732
|
+
r."stopReasonContext" AS "stopReasonContext"`;
|
|
19656
19733
|
function fieldSql(registry, field) {
|
|
19657
19734
|
const sql = registry[field];
|
|
19658
19735
|
if (sql === void 0) throw new Error(`Unsupported trusted trace-query field: ${field}`);
|
|
@@ -20009,8 +20086,8 @@ function compilePostgresTraceScope(schema, selection, relationCollections, scope
|
|
|
20009
20086
|
s."traceId",
|
|
20010
20087
|
s."name",
|
|
20011
20088
|
s."spanType",
|
|
20012
|
-
CASE WHEN jsonb_typeof(s."attributes" -> 'model') = 'string' THEN s."attributes" ->> 'model' END AS "model",
|
|
20013
|
-
CASE WHEN jsonb_typeof(s."attributes" -> 'provider') = 'string' THEN s."attributes" ->> 'provider' END AS "provider",
|
|
20089
|
+
COALESCE(s."model", CASE WHEN jsonb_typeof(s."attributes" -> 'model') = 'string' THEN s."attributes" ->> 'model' END) AS "model",
|
|
20090
|
+
COALESCE(s."provider", CASE WHEN jsonb_typeof(s."attributes" -> 'provider') = 'string' THEN s."attributes" ->> 'provider' END) AS "provider",
|
|
20014
20091
|
s."startedAt",
|
|
20015
20092
|
CASE WHEN s."isPending" THEN NULL ELSE s."endedAt" END AS "endedAt",
|
|
20016
20093
|
CASE
|
|
@@ -20020,6 +20097,8 @@ function compilePostgresTraceScope(schema, selection, relationCollections, scope
|
|
|
20020
20097
|
s."timeToFirstChunkMs",
|
|
20021
20098
|
s."timeToFirstTokenMs",
|
|
20022
20099
|
CASE WHEN s."error" IS NOT NULL THEN 'error' ELSE 'success' END AS "status",
|
|
20100
|
+
s."outcome",
|
|
20101
|
+
s."stopReason",
|
|
20023
20102
|
s."error",
|
|
20024
20103
|
s."entityType",
|
|
20025
20104
|
s."entityId",
|
|
@@ -20397,7 +20476,12 @@ function traceRowToResult(row) {
|
|
|
20397
20476
|
entityName: row.entityName == null ? null : String(row.entityName),
|
|
20398
20477
|
entityType: row.entityType == null ? null : String(row.entityType),
|
|
20399
20478
|
environment: row.environment == null ? null : String(row.environment),
|
|
20400
|
-
status: row.status
|
|
20479
|
+
status: row.status,
|
|
20480
|
+
...traceQueryOutcomeFieldsSupported && {
|
|
20481
|
+
outcome: row.outcome == null ? null : String(row.outcome),
|
|
20482
|
+
stopReason: row.stopReason == null ? null : String(row.stopReason),
|
|
20483
|
+
stopReasonContext: row.stopReasonContext ?? null
|
|
20484
|
+
}
|
|
20401
20485
|
};
|
|
20402
20486
|
}
|
|
20403
20487
|
async function queryTraces(client, schema, plan, timeoutMs) {
|
|
@@ -20550,7 +20634,9 @@ const fields = [
|
|
|
20550
20634
|
"environment",
|
|
20551
20635
|
"executionSource",
|
|
20552
20636
|
"timeToFirstChunkMs",
|
|
20553
|
-
"timeToFirstTokenMs"
|
|
20637
|
+
"timeToFirstTokenMs",
|
|
20638
|
+
"outcome",
|
|
20639
|
+
"stopReason"
|
|
20554
20640
|
];
|
|
20555
20641
|
const identities = identityFields.map((field) => `"${field}"`).join(", ");
|
|
20556
20642
|
const identityOrder = identityFields.map((field) => `"${field}" COLLATE "C" ASC NULLS LAST`).join(", ");
|
|
@@ -20600,8 +20686,6 @@ function compilePostgresSpanSelection(schema, plan) {
|
|
|
20600
20686
|
};
|
|
20601
20687
|
values.push(...predicate.values);
|
|
20602
20688
|
const table = qualifiedTable(schema, TABLE_SPAN_EVENTS);
|
|
20603
|
-
const legacyModelFields = coreStorage.SPAN_QUERY_FIELD_REGISTRY ? "" : `CASE WHEN jsonb_typeof(attributes -> 'model') = 'string' THEN attributes ->> 'model' END AS model,
|
|
20604
|
-
CASE WHEN jsonb_typeof(attributes -> 'provider') = 'string' THEN attributes ->> 'provider' END AS provider,`;
|
|
20605
20689
|
return {
|
|
20606
20690
|
ctes: [
|
|
20607
20691
|
`candidate_ids AS MATERIALIZED (
|
|
@@ -20612,7 +20696,7 @@ function compilePostgresSpanSelection(schema, plan) {
|
|
|
20612
20696
|
`current_spans AS MATERIALIZED (
|
|
20613
20697
|
SELECT DISTINCT ON (${identities})
|
|
20614
20698
|
${fields.map((field) => `"${field}"`).join(", ")}, "startedAt", "endedAt", "cursorId"::text AS version,
|
|
20615
|
-
|
|
20699
|
+
"model", "provider",
|
|
20616
20700
|
(EXTRACT(EPOCH FROM ("endedAt" - "startedAt")) * 1000)::float8 AS "durationMs",
|
|
20617
20701
|
CASE WHEN error IS NULL THEN 'success' ELSE 'error' END AS status,
|
|
20618
20702
|
error IS NOT NULL AS "hasError"
|
|
@@ -20682,10 +20766,14 @@ async function querySpans(client, schema, plan, timeoutMs) {
|
|
|
20682
20766
|
return runWithPostgresTraceQueryTimeout(client, timeoutMs, async (tx) => {
|
|
20683
20767
|
const query = compilePostgresSpanQuery(schema, plan);
|
|
20684
20768
|
const rows = await tx.any(query.text, query.values);
|
|
20685
|
-
const selected = rows.map(({ version: _version, startedAt, endedAt, timeToFirstChunkMs, timeToFirstTokenMs, ...row }) => ({
|
|
20769
|
+
const selected = rows.map(({ version: _version, startedAt, endedAt, timeToFirstChunkMs, timeToFirstTokenMs, outcome, stopReason, ...row }) => ({
|
|
20686
20770
|
...row,
|
|
20687
20771
|
...timeToFirstChunkSupported && { timeToFirstChunkMs },
|
|
20688
20772
|
...timeToFirstTokenSupported && { timeToFirstTokenMs },
|
|
20773
|
+
...spanQueryOutcomeFieldsSupported && {
|
|
20774
|
+
outcome,
|
|
20775
|
+
stopReason
|
|
20776
|
+
},
|
|
20689
20777
|
startedAt: startedAt.toISOString(),
|
|
20690
20778
|
endedAt: endedAt.toISOString()
|
|
20691
20779
|
}));
|
|
@@ -20703,18 +20791,22 @@ async function querySpans(client, schema, plan, timeoutMs) {
|
|
|
20703
20791
|
payloadValues.push(row.version);
|
|
20704
20792
|
return `(${key} AND "cursorId" = $${payloadValues.length}::bigint)`;
|
|
20705
20793
|
}).join(" OR ");
|
|
20706
|
-
const payloadRows = await tx.any(`SELECT ${identities},
|
|
20707
|
-
CASE WHEN jsonb_typeof(attributes -> 'model') = 'string' THEN attributes ->> 'model' END AS model,
|
|
20708
|
-
CASE WHEN jsonb_typeof(attributes -> 'provider') = 'string' THEN attributes ->> 'provider' END AS provider,
|
|
20794
|
+
const payloadRows = await tx.any(`SELECT ${identities}, "stopReasonContext",
|
|
20795
|
+
COALESCE("model", CASE WHEN jsonb_typeof(attributes -> 'model') = 'string' THEN attributes ->> 'model' END) AS model,
|
|
20796
|
+
COALESCE("provider", CASE WHEN jsonb_typeof(attributes -> 'provider') = 'string' THEN attributes ->> 'provider' END) AS provider,
|
|
20709
20797
|
${PREVIEW_PAYLOADS$1.map(([preview, payload]) => `"${preview}", CASE WHEN ${missingPreviewSql(`"${preview}"`)} THEN "${payload}" END AS "${payload}"`).join(",\n ")}
|
|
20710
20798
|
FROM ${qualifiedTable(schema, TABLE_SPAN_EVENTS)} WHERE ${payloadWhere}`, payloadValues);
|
|
20711
20799
|
const payloads = payloadRows.map(toSpanQueryPayload);
|
|
20712
20800
|
const metadata = new Map(payloadRows.map((row) => [coreStorage.spanQueryIdentityKey(row), row]));
|
|
20713
|
-
const hydrated = selected.map((row) =>
|
|
20714
|
-
|
|
20715
|
-
|
|
20716
|
-
|
|
20717
|
-
|
|
20801
|
+
const hydrated = selected.map((row) => {
|
|
20802
|
+
const stored = metadata.get(coreStorage.spanQueryIdentityKey(row));
|
|
20803
|
+
return {
|
|
20804
|
+
...row,
|
|
20805
|
+
model: stored?.model ?? null,
|
|
20806
|
+
provider: stored?.provider ?? null,
|
|
20807
|
+
...spanQueryOutcomeFieldsSupported && { stopReasonContext: stored?.stopReasonContext ?? null }
|
|
20808
|
+
};
|
|
20809
|
+
});
|
|
20718
20810
|
let metrics = [];
|
|
20719
20811
|
if (!coreStorage.SPAN_QUERY_FIELD_REGISTRY) {
|
|
20720
20812
|
await remaining();
|
|
@@ -20956,6 +21048,8 @@ const DIMENSION_SQL = {
|
|
|
20956
21048
|
entityId: "r.\"entityId\"",
|
|
20957
21049
|
environment: "r.\"environment\"",
|
|
20958
21050
|
status: TRACE_STATUS_SQL,
|
|
21051
|
+
outcome: "r.\"outcome\"",
|
|
21052
|
+
stopReason: "r.\"stopReason\"",
|
|
20959
21053
|
serviceName: "r.\"serviceName\"",
|
|
20960
21054
|
executionSource: "r.\"executionSource\"",
|
|
20961
21055
|
threadId: "r.\"threadId\"",
|
|
@@ -20978,6 +21072,8 @@ const SPAN_DIMENSION_SQL = Object.fromEntries([
|
|
|
20978
21072
|
"rootEntityName",
|
|
20979
21073
|
"environment",
|
|
20980
21074
|
"status",
|
|
21075
|
+
"outcome",
|
|
21076
|
+
"stopReason",
|
|
20981
21077
|
"serviceName",
|
|
20982
21078
|
"executionSource",
|
|
20983
21079
|
"threadId",
|
|
@@ -20985,7 +21081,9 @@ const SPAN_DIMENSION_SQL = Object.fromEntries([
|
|
|
20985
21081
|
"userId",
|
|
20986
21082
|
"sessionId",
|
|
20987
21083
|
"organizationId",
|
|
20988
|
-
"experimentId"
|
|
21084
|
+
"experimentId",
|
|
21085
|
+
"model",
|
|
21086
|
+
"provider"
|
|
20989
21087
|
].map((field) => [field, `r."${field}"`]));
|
|
20990
21088
|
const PERCENTILES = {
|
|
20991
21089
|
"duration.p50": .5,
|
|
@@ -22038,8 +22136,12 @@ async function dangerouslyClearTracing(client, schema) {
|
|
|
22038
22136
|
* application database — observability writes will degrade app performance.
|
|
22039
22137
|
* Use it through `MastraCompositeStore` with a dedicated Postgres connection.
|
|
22040
22138
|
*/
|
|
22041
|
-
const spanQueryFeatures = typeof coreStorage.planSpanQuery === "function" ? [
|
|
22042
|
-
|
|
22139
|
+
const spanQueryFeatures = typeof coreStorage.planSpanQuery === "function" ? [
|
|
22140
|
+
"span-query",
|
|
22141
|
+
"span-query-context-fields",
|
|
22142
|
+
..."model" in (coreStorage.SPAN_QUERY_FIELD_REGISTRY ?? {}) ? ["span-query-model-fields"] : []
|
|
22143
|
+
] : [];
|
|
22144
|
+
const spanAggregateFeatures = typeof coreStorage.planSpanAggregate === "function" ? ["span-aggregate", ..."model" in (coreStorage.SPAN_AGGREGATE_DIMENSION_REGISTRY ?? {}) ? ["span-aggregate-model-dimensions"] : []] : [];
|
|
22043
22145
|
function wrapError(op, error, details) {
|
|
22044
22146
|
if (error instanceof MastraError || error instanceof coreStorage.TraceQueryCursorError || error instanceof coreStorage.TraceQueryExecutionError || error instanceof coreStorage.TraceQueryResourceLimitError) throw error;
|
|
22045
22147
|
throw new MastraError({
|
|
@@ -22251,6 +22353,7 @@ var ObservabilityStoragePostgresVNext = class ObservabilityStoragePostgresVNext
|
|
|
22251
22353
|
"feedback",
|
|
22252
22354
|
"trace-query-context-ids",
|
|
22253
22355
|
...timingFeatures,
|
|
22356
|
+
...outcomeFeatures,
|
|
22254
22357
|
"trace-query-root-span-fields",
|
|
22255
22358
|
"trace-query-root-entity-id"
|
|
22256
22359
|
];
|
|
@@ -22276,6 +22379,7 @@ var ObservabilityStoragePostgresVNext = class ObservabilityStoragePostgresVNext
|
|
|
22276
22379
|
"feedback",
|
|
22277
22380
|
"trace-query-context-ids",
|
|
22278
22381
|
...timingFeatures,
|
|
22382
|
+
...outcomeFeatures,
|
|
22279
22383
|
"trace-query-root-span-fields",
|
|
22280
22384
|
"trace-query-root-entity-id"
|
|
22281
22385
|
];
|