@mastra/pg 1.32.0-alpha.6 → 1.33.0-alpha.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/dist/_types/@internal_core/dist/knowledge-compat/index.d.ts +48 -48
- package/dist/_types/@internal_core/dist/memory/index.d.ts +12 -13
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/docs-memory-semantic-recall.md +2 -2
- package/dist/docs/references/docs-memory-working-memory.md +3 -3
- package/dist/docs/references/docs-storage.md +1 -1
- package/dist/docs/references/integrations-databases-postgresql.md +1 -1
- package/dist/docs/references/reference-memory-memory-class.md +3 -3
- package/dist/docs/references/reference-processors-message-history-processor.md +2 -2
- package/dist/docs/references/reference-processors-semantic-recall-processor.md +2 -2
- package/dist/docs/references/reference-processors-working-memory-processor.md +2 -2
- package/dist/docs/references/reference-rag-chunking-and-embedding.md +1 -1
- package/dist/docs/references/reference-rag-metadata-filters.md +1 -1
- package/dist/docs/references/reference-rag-retrieval.md +13 -13
- package/dist/docs/references/reference-tools-vector-query-tool.md +1 -1
- package/dist/docs/references/reference-vectors-pg.md +1 -1
- package/dist/index.cjs +112 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +112 -30
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/observability/v-next/index.d.ts +3 -2
- package/dist/storage/domains/observability/v-next/index.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/span-query.d.ts +9 -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 +7 -1
- package/dist/storage/domains/observability/v-next/trace-aggregate.d.ts.map +1 -1
- package/package.json +8 -8
package/dist/index.js
CHANGED
|
@@ -20256,7 +20256,12 @@ function afterCursor(plan, values) {
|
|
|
20256
20256
|
}
|
|
20257
20257
|
return `(${terms.join(" OR ")})`;
|
|
20258
20258
|
}
|
|
20259
|
-
|
|
20259
|
+
/**
|
|
20260
|
+
* The spans `querySpans()` pages through, as a `selected` CTE: the latest completed copy of each
|
|
20261
|
+
* span that starts in the window and matches `where`. `aggregateSpans()` groups the same CTE.
|
|
20262
|
+
* `values` holds the CTEs' parameters; callers append their own.
|
|
20263
|
+
*/
|
|
20264
|
+
function compilePostgresSpanSelection(schema, plan) {
|
|
20260
20265
|
const values = [plan.timeRange.from, plan.timeRange.to];
|
|
20261
20266
|
const scope = [];
|
|
20262
20267
|
if (plan.scope) {
|
|
@@ -20272,17 +20277,17 @@ function compilePostgresSpanQuery(schema, plan) {
|
|
|
20272
20277
|
values: []
|
|
20273
20278
|
};
|
|
20274
20279
|
values.push(...predicate.values);
|
|
20275
|
-
const after = afterCursor(plan, values);
|
|
20276
|
-
values.push(plan.limit + 1);
|
|
20277
20280
|
const table = qualifiedTable(schema, TABLE_SPAN_EVENTS);
|
|
20278
20281
|
const legacyModelFields = coreStorage.SPAN_QUERY_FIELD_REGISTRY ? "" : `CASE WHEN jsonb_typeof(attributes -> 'model') = 'string' THEN attributes ->> 'model' END AS model,
|
|
20279
20282
|
CASE WHEN jsonb_typeof(attributes -> 'provider') = 'string' THEN attributes ->> 'provider' END AS provider,`;
|
|
20280
20283
|
return {
|
|
20281
|
-
|
|
20284
|
+
ctes: [
|
|
20285
|
+
`candidate_ids AS MATERIALIZED (
|
|
20282
20286
|
SELECT DISTINCT ${identities} FROM ${table}
|
|
20283
20287
|
WHERE "startedAt" >= $1 AND "startedAt" < $2 AND "endedAt" >= $1 AND NOT "isPending"
|
|
20284
20288
|
${scope.length ? `AND ${scope.join(" AND ")}` : ""}
|
|
20285
|
-
)
|
|
20289
|
+
)`,
|
|
20290
|
+
`current_spans AS MATERIALIZED (
|
|
20286
20291
|
SELECT DISTINCT ON (${identities})
|
|
20287
20292
|
${fields.map((field) => `"${field}"`).join(", ")}, "startedAt", "endedAt", "cursorId"::text AS version,
|
|
20288
20293
|
${legacyModelFields}
|
|
@@ -20296,9 +20301,23 @@ function compilePostgresSpanQuery(schema, plan) {
|
|
|
20296
20301
|
SELECT "organizationId" IS NULL, COALESCE("organizationId", ''), "resourceId" IS NULL, COALESCE("resourceId", ''), "traceId", "spanId" FROM candidate_ids
|
|
20297
20302
|
) ${scope.length ? `AND ${scope.join(" AND ")}` : ""}
|
|
20298
20303
|
ORDER BY ${identities}, "endedAt" DESC, "cursorId" DESC
|
|
20299
|
-
)
|
|
20304
|
+
)`,
|
|
20305
|
+
`candidates AS (
|
|
20300
20306
|
SELECT *, CASE WHEN "hasError" THEN 'error' ELSE NULL END AS error FROM current_spans
|
|
20301
|
-
)
|
|
20307
|
+
)`,
|
|
20308
|
+
`selected AS (
|
|
20309
|
+
SELECT * FROM candidates s WHERE s."startedAt" >= $1 AND s."startedAt" < $2 AND (${predicate.sql})
|
|
20310
|
+
)`
|
|
20311
|
+
],
|
|
20312
|
+
values
|
|
20313
|
+
};
|
|
20314
|
+
}
|
|
20315
|
+
function compilePostgresSpanQuery(schema, plan) {
|
|
20316
|
+
const { ctes, values } = compilePostgresSpanSelection(schema, plan);
|
|
20317
|
+
const after = afterCursor(plan, values);
|
|
20318
|
+
values.push(plan.limit + 1);
|
|
20319
|
+
return {
|
|
20320
|
+
text: `WITH ${ctes.join(", ")}
|
|
20302
20321
|
SELECT ${[
|
|
20303
20322
|
...fields,
|
|
20304
20323
|
"startedAt",
|
|
@@ -20307,7 +20326,7 @@ function compilePostgresSpanQuery(schema, plan) {
|
|
|
20307
20326
|
"status",
|
|
20308
20327
|
"version"
|
|
20309
20328
|
].map((field) => `s."${field}"`).join(", ")}
|
|
20310
|
-
FROM
|
|
20329
|
+
FROM selected s WHERE ${after}
|
|
20311
20330
|
ORDER BY s."${plan.orderBy.field}" ${plan.orderBy.direction === "asc" ? "ASC" : "DESC"} NULLS LAST, ${identityOrder}
|
|
20312
20331
|
LIMIT $${values.length}`,
|
|
20313
20332
|
values
|
|
@@ -20641,6 +20660,28 @@ const DIMENSION_SQL = {
|
|
|
20641
20660
|
organizationId: "r.\"organizationId\"",
|
|
20642
20661
|
experimentId: "r.\"experimentId\""
|
|
20643
20662
|
};
|
|
20663
|
+
/** Span column expressions (alias `r`, a `selected` span row) for each groupable span dimension. */
|
|
20664
|
+
const SPAN_DIMENSION_SQL = Object.fromEntries([
|
|
20665
|
+
"name",
|
|
20666
|
+
"spanType",
|
|
20667
|
+
"entityType",
|
|
20668
|
+
"entityId",
|
|
20669
|
+
"entityName",
|
|
20670
|
+
"parentEntityType",
|
|
20671
|
+
"parentEntityName",
|
|
20672
|
+
"rootEntityType",
|
|
20673
|
+
"rootEntityName",
|
|
20674
|
+
"environment",
|
|
20675
|
+
"status",
|
|
20676
|
+
"serviceName",
|
|
20677
|
+
"executionSource",
|
|
20678
|
+
"threadId",
|
|
20679
|
+
"resourceId",
|
|
20680
|
+
"userId",
|
|
20681
|
+
"sessionId",
|
|
20682
|
+
"organizationId",
|
|
20683
|
+
"experimentId"
|
|
20684
|
+
].map((field) => [field, `r."${field}"`]));
|
|
20644
20685
|
const PERCENTILES = {
|
|
20645
20686
|
"duration.p50": .5,
|
|
20646
20687
|
"duration.p90": .9,
|
|
@@ -20666,16 +20707,43 @@ const COMPARISON_SQL = {
|
|
|
20666
20707
|
*/
|
|
20667
20708
|
function compilePostgresTraceAggregate(schema, plan) {
|
|
20668
20709
|
const { ctes, values } = compilePostgresTraceCandidates(schema, plan, "r.*");
|
|
20710
|
+
return compilePostgresAggregate(schema, plan, {
|
|
20711
|
+
ctes,
|
|
20712
|
+
values,
|
|
20713
|
+
from: "candidates",
|
|
20714
|
+
dimensionSql: (field, param) => {
|
|
20715
|
+
if (field.startsWith("metadata.")) return traceMetadataValueSql(param(field.slice(9)));
|
|
20716
|
+
return lookupDimensionSql(DIMENSION_SQL, field);
|
|
20717
|
+
},
|
|
20718
|
+
usageKey: ["traceId"]
|
|
20719
|
+
});
|
|
20720
|
+
}
|
|
20721
|
+
/**
|
|
20722
|
+
* Compiles a trusted span aggregate plan over the spans `querySpans()` selects. Usage is
|
|
20723
|
+
* attributed by `(traceId, spanId)`, so only the span that recorded a metric row carries it.
|
|
20724
|
+
*/
|
|
20725
|
+
function compilePostgresSpanAggregate(schema, plan) {
|
|
20726
|
+
const { ctes, values } = compilePostgresSpanSelection(schema, plan);
|
|
20727
|
+
return compilePostgresAggregate(schema, plan, {
|
|
20728
|
+
ctes,
|
|
20729
|
+
values,
|
|
20730
|
+
from: "selected",
|
|
20731
|
+
dimensionSql: (field) => lookupDimensionSql(SPAN_DIMENSION_SQL, field),
|
|
20732
|
+
usageKey: ["traceId", "spanId"]
|
|
20733
|
+
});
|
|
20734
|
+
}
|
|
20735
|
+
function lookupDimensionSql(columns, field) {
|
|
20736
|
+
const sql = Object.hasOwn(columns, field) ? columns[field] : void 0;
|
|
20737
|
+
if (sql === void 0) throw new Error(`Unsupported trusted aggregate field: ${field}`);
|
|
20738
|
+
return sql;
|
|
20739
|
+
}
|
|
20740
|
+
function compilePostgresAggregate(schema, plan, source) {
|
|
20741
|
+
const { ctes, values } = source;
|
|
20669
20742
|
const param = (value) => {
|
|
20670
20743
|
values.push(value);
|
|
20671
20744
|
return `$${values.length}`;
|
|
20672
20745
|
};
|
|
20673
|
-
const dimensionSql = (field) =>
|
|
20674
|
-
if (field.startsWith("metadata.")) return traceMetadataValueSql(param(field.slice(9)));
|
|
20675
|
-
const sql = Object.hasOwn(DIMENSION_SQL, field) ? DIMENSION_SQL[field] : void 0;
|
|
20676
|
-
if (sql === void 0) throw new Error(`Unsupported trusted trace-aggregate field: ${field}`);
|
|
20677
|
-
return sql;
|
|
20678
|
-
};
|
|
20746
|
+
const dimensionSql = (field) => source.dimensionSql(field, param);
|
|
20679
20747
|
const distinctSql = (field) => field === "traceId" ? "r.\"traceId\"" : dimensionSql(field);
|
|
20680
20748
|
const dimensionColumns = plan.dimensions.map((_, index) => `"d${index}"`);
|
|
20681
20749
|
const distinctColumns = /* @__PURE__ */ new Map();
|
|
@@ -20696,14 +20764,14 @@ function compilePostgresTraceAggregate(schema, plan) {
|
|
|
20696
20764
|
const hasCost = measureKinds.has("cost");
|
|
20697
20765
|
let usageJoin = "";
|
|
20698
20766
|
if (hasCost || measureKinds.has("tokens")) {
|
|
20699
|
-
ctes.push(...compileUsageCtes(schema, plan, param));
|
|
20700
|
-
usageJoin =
|
|
20767
|
+
ctes.push(...compileUsageCtes(schema, plan, source, param));
|
|
20768
|
+
usageJoin = `\n LEFT JOIN usage u ON ${source.usageKey.map((key) => `u."${key}" = r."${key}"`).join(" AND ")}`;
|
|
20701
20769
|
USAGE_METRIC_NAMES.forEach((_, index) => factColumns.push(`CASE WHEN u."traceId" IS NOT NULL THEN COALESCE(u."t${index}", 0) END AS "t${index}"`));
|
|
20702
20770
|
factColumns.push(`u."traceId" IS NOT NULL AS "usageBearing"`, `CASE WHEN u."priced" THEN u."cost" END AS "traceCost"`, `COALESCE(u."priced" AND NOT u."pricingFailure", FALSE) AS "covered"`, `u."unitMin"`, `u."unitMax"`);
|
|
20703
20771
|
}
|
|
20704
20772
|
ctes.push(`facts AS (
|
|
20705
20773
|
SELECT ${factColumns.join(",\n ")}
|
|
20706
|
-
FROM
|
|
20774
|
+
FROM ${source.from} r${usageJoin}
|
|
20707
20775
|
)`);
|
|
20708
20776
|
const mixedUnitsSql = (alias) => `MIN(${alias}"unitMin" COLLATE "C") <> MAX(${alias}"unitMax" COLLATE "C")`;
|
|
20709
20777
|
const measureSql = (name, alias = "") => {
|
|
@@ -20819,36 +20887,39 @@ function usageMetricIndex(name) {
|
|
|
20819
20887
|
return index;
|
|
20820
20888
|
}
|
|
20821
20889
|
/**
|
|
20822
|
-
* Builds `usage`: one row per
|
|
20823
|
-
* per-name token sums (`t<i>`, indexed by `TRACE_AGGREGATE_USAGE_METRIC_NAMES`) and
|
|
20824
|
-
* pricing state. Metric rows are matched by
|
|
20825
|
-
* `timestamp >= from` only: a trace that starts in the window can emit metrics
|
|
20826
|
-
* the
|
|
20890
|
+
* Builds `usage`: one row per population row (trace, or span) that has at least one token metric
|
|
20891
|
+
* row, holding per-name token sums (`t<i>`, indexed by `TRACE_AGGREGATE_USAGE_METRIC_NAMES`) and
|
|
20892
|
+
* its pricing state. Metric rows are matched by the source's usage key, usage metric name, tenant
|
|
20893
|
+
* scope, and `timestamp >= from` only: a trace or span that starts in the window can emit metrics
|
|
20894
|
+
* after `to`, and the population semi-join already bounds the scan.
|
|
20827
20895
|
*
|
|
20828
20896
|
* Rows are deduplicated on `metricId` alone. The primary key is (`metricId`, `timestamp`)
|
|
20829
20897
|
* because the table is partitioned by timestamp, so retried copies with different timestamps
|
|
20830
20898
|
* are both stored.
|
|
20831
20899
|
*/
|
|
20832
|
-
function compileUsageCtes(schema, plan, param) {
|
|
20900
|
+
function compileUsageCtes(schema, plan, source, param) {
|
|
20901
|
+
const key = source.usageKey.map((column) => `"${column}"`).join(", ");
|
|
20902
|
+
const metricKey = source.usageKey.map((column) => `m."${column}"`).join(", ");
|
|
20833
20903
|
const scopeConditions = plan.scope ? [`m."organizationId" = ${param(plan.scope.organizationId)}`, ...plan.scope.resourceId === void 0 ? [] : [`m."resourceId" = ${param(plan.scope.resourceId)}`]] : [];
|
|
20834
20904
|
const rowConditions = [
|
|
20835
|
-
|
|
20905
|
+
`${source.usageKey.length === 1 ? metricKey : `(${metricKey})`} IN (SELECT ${key} FROM ${source.from})`,
|
|
20836
20906
|
`m."name" = ANY(${param(USAGE_METRIC_NAMES)}::text[])`,
|
|
20837
20907
|
`m."timestamp" >= ${param(plan.timeRange.from)}::timestamptz`,
|
|
20838
20908
|
...scopeConditions
|
|
20839
20909
|
];
|
|
20840
20910
|
const costRow = `"name" = ANY(${param(coreStorage.TRACE_AGGREGATE_COST_METRIC_NAMES)}::text[])`;
|
|
20841
|
-
const priced = `${costRow} AND "estimatedCost" IS NOT NULL AND "costUnit" IS NOT NULL AND NOT "hasError"`;
|
|
20911
|
+
const priced = `${costRow} AND "estimatedCost" IS NOT NULL AND "costUnit" IS NOT NULL AND (NOT "hasError" OR "partialCost")`;
|
|
20842
20912
|
const failed = `${costRow} AND ("hasError" OR ("estimatedCost" IS NOT NULL AND "costUnit" IS NULL))`;
|
|
20843
20913
|
const tokenColumns = USAGE_METRIC_NAMES.map((name, index) => `SUM("value") FILTER (WHERE "name" = ${param(name)}) AS "t${index}"`);
|
|
20844
20914
|
return [`usage_rows AS (
|
|
20845
|
-
SELECT DISTINCT ON (m."metricId")
|
|
20846
|
-
COALESCE(jsonb_typeof(m."costMetadata" -> 'error'), 'null') <> 'null' AS "hasError"
|
|
20915
|
+
SELECT DISTINCT ON (m."metricId") ${metricKey}, m."name", m."value", m."estimatedCost", m."costUnit",
|
|
20916
|
+
COALESCE(jsonb_typeof(m."costMetadata" -> 'error'), 'null') <> 'null' AS "hasError",
|
|
20917
|
+
COALESCE(m."costMetadata" ->> 'error' = 'partial_cost', FALSE) AS "partialCost"
|
|
20847
20918
|
FROM ${qualifiedTable(schema, TABLE_METRIC_EVENTS)} m
|
|
20848
20919
|
WHERE ${rowConditions.join("\n AND ")}
|
|
20849
20920
|
ORDER BY m."metricId", m."timestamp"
|
|
20850
20921
|
)`, `usage AS (
|
|
20851
|
-
SELECT
|
|
20922
|
+
SELECT ${key},
|
|
20852
20923
|
${tokenColumns.join(",\n ")},
|
|
20853
20924
|
SUM("estimatedCost") FILTER (WHERE ${priced}) AS "cost",
|
|
20854
20925
|
bool_or(${priced}) AS "priced",
|
|
@@ -20856,7 +20927,7 @@ function compileUsageCtes(schema, plan, param) {
|
|
|
20856
20927
|
MIN("costUnit" COLLATE "C") FILTER (WHERE ${priced}) AS "unitMin",
|
|
20857
20928
|
MAX("costUnit" COLLATE "C") FILTER (WHERE ${priced}) AS "unitMax"
|
|
20858
20929
|
FROM usage_rows
|
|
20859
|
-
GROUP BY
|
|
20930
|
+
GROUP BY ${key}
|
|
20860
20931
|
)`];
|
|
20861
20932
|
}
|
|
20862
20933
|
function nullableNumber(value) {
|
|
@@ -20866,7 +20937,12 @@ function toIsoTimestamp(value) {
|
|
|
20866
20937
|
return value instanceof Date ? value.toISOString() : new Date(value).toISOString();
|
|
20867
20938
|
}
|
|
20868
20939
|
async function aggregateTraces(client, schema, plan, timeoutMs) {
|
|
20869
|
-
|
|
20940
|
+
return runAggregate(client, plan, compilePostgresTraceAggregate(schema, plan), timeoutMs);
|
|
20941
|
+
}
|
|
20942
|
+
async function aggregateSpans(client, schema, plan, timeoutMs) {
|
|
20943
|
+
return runAggregate(client, plan, compilePostgresSpanAggregate(schema, plan), timeoutMs);
|
|
20944
|
+
}
|
|
20945
|
+
async function runAggregate(client, plan, compiled, timeoutMs) {
|
|
20870
20946
|
const result = await runWithPostgresTraceQueryTimeout(client, timeoutMs, (transaction) => transaction.any(compiled.text, compiled.values));
|
|
20871
20947
|
let truncated;
|
|
20872
20948
|
let resultRows;
|
|
@@ -21662,6 +21738,7 @@ async function dangerouslyClearTracing(client, schema) {
|
|
|
21662
21738
|
* Use it through `MastraCompositeStore` with a dedicated Postgres connection.
|
|
21663
21739
|
*/
|
|
21664
21740
|
const spanQueryFeatures = typeof coreStorage.planSpanQuery === "function" ? ["span-query", "span-query-context-fields"] : [];
|
|
21741
|
+
const spanAggregateFeatures = typeof coreStorage.planSpanAggregate === "function" ? ["span-aggregate"] : [];
|
|
21665
21742
|
function wrapError(op, error, details) {
|
|
21666
21743
|
if (error instanceof MastraError || error instanceof coreStorage.TraceQueryCursorError || error instanceof coreStorage.TraceQueryExecutionError || error instanceof coreStorage.TraceQueryResourceLimitError) throw error;
|
|
21667
21744
|
throw new MastraError({
|
|
@@ -21852,6 +21929,7 @@ var ObservabilityStoragePostgresVNext = class ObservabilityStoragePostgresVNext
|
|
|
21852
21929
|
"trace-query",
|
|
21853
21930
|
"trace-aggregate",
|
|
21854
21931
|
...spanQueryFeatures,
|
|
21932
|
+
...spanAggregateFeatures,
|
|
21855
21933
|
...typeof coreStorage.planThreadRowsQuery === "function" ? ["thread-query-rows"] : [],
|
|
21856
21934
|
"trace-query-root-duration",
|
|
21857
21935
|
"trace-query-discovery",
|
|
@@ -21876,6 +21954,7 @@ var ObservabilityStoragePostgresVNext = class ObservabilityStoragePostgresVNext
|
|
|
21876
21954
|
"trace-query",
|
|
21877
21955
|
"trace-aggregate",
|
|
21878
21956
|
...spanQueryFeatures,
|
|
21957
|
+
...spanAggregateFeatures,
|
|
21879
21958
|
...typeof coreStorage.planThreadRowsQuery === "function" ? ["thread-query-rows"] : [],
|
|
21880
21959
|
"trace-query-root-duration",
|
|
21881
21960
|
"trace-query-discovery",
|
|
@@ -21940,6 +22019,9 @@ var ObservabilityStoragePostgresVNext = class ObservabilityStoragePostgresVNext
|
|
|
21940
22019
|
async aggregateTraces(plan) {
|
|
21941
22020
|
return this.#run("AGGREGATE_TRACES", () => aggregateTraces(this.#readClient, this.#schema, plan, this.#traceQueryTimeoutMs));
|
|
21942
22021
|
}
|
|
22022
|
+
async aggregateSpans(plan) {
|
|
22023
|
+
return this.#run("AGGREGATE_SPANS", () => aggregateSpans(this.#readClient, this.#schema, plan, this.#traceQueryTimeoutMs));
|
|
22024
|
+
}
|
|
21943
22025
|
async getTraceQueryObservedFields(plan) {
|
|
21944
22026
|
return this.#run("GET_TRACE_QUERY_OBSERVED_FIELDS", () => getTraceQueryObservedFields(this.#readClient, this.#schema, plan, this.#traceQueryTimeoutMs));
|
|
21945
22027
|
}
|