@mastra/pg 1.32.0-alpha.2 → 1.32.0-alpha.3
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/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/index.cjs +275 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +275 -8
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/memory/index.d.ts +1 -1
- package/dist/storage/domains/memory/index.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/index.d.ts +4 -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 +1 -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 +1 -0
- package/dist/storage/domains/observability/v-next/span-query.d.ts.map +1 -1
- package/dist/storage/domains/observability/v-next/thread-query.d.ts +49 -0
- package/dist/storage/domains/observability/v-next/thread-query.d.ts.map +1 -0
- 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 +4 -0
- package/dist/storage/domains/observability/v-next/trace-query.d.ts.map +1 -1
- package/dist/storage/domains/skills/index.d.ts.map +1 -1
- package/package.json +10 -11
package/dist/docs/SKILL.md
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -19209,6 +19209,9 @@ async function getScorePercentiles(client, schema, args) {
|
|
|
19209
19209
|
//#endregion
|
|
19210
19210
|
//#region src/storage/domains/observability/v-next/trace-query.ts
|
|
19211
19211
|
const TRACE_STATUS_SQL = `CASE WHEN r."error" IS NOT NULL THEN 'error' ELSE 'success' END`;
|
|
19212
|
+
/** Core versions without the field reject it in strict query results, so it is only returned when core knows it. */
|
|
19213
|
+
const timeToFirstChunkSupported = "timeToFirstChunkMs" in _mastra_core_storage.TRACE_QUERY_FIELD_REGISTRY.trace;
|
|
19214
|
+
const timeToFirstChunkFeatures = timeToFirstChunkSupported ? ["trace-query-time-to-first-chunk"] : [];
|
|
19212
19215
|
function durationMsSql(startedAt, endedAt) {
|
|
19213
19216
|
return `EXTRACT(EPOCH FROM (${endedAt} - ${startedAt}))::numeric * 1000`;
|
|
19214
19217
|
}
|
|
@@ -19223,8 +19226,11 @@ const TRACE_FIELDS = {
|
|
|
19223
19226
|
startedAt: "r.\"startedAt\"",
|
|
19224
19227
|
endedAt: "r.\"endedAt\"",
|
|
19225
19228
|
durationMs: durationMsSql("r.\"startedAt\"", "r.\"endedAt\""),
|
|
19229
|
+
timeToFirstChunkMs: "r.\"timeToFirstChunkMs\"",
|
|
19226
19230
|
entityName: "r.\"entityName\"",
|
|
19227
19231
|
entityType: "r.\"entityType\"",
|
|
19232
|
+
name: "r.\"name\"",
|
|
19233
|
+
spanType: "r.\"spanType\"",
|
|
19228
19234
|
environment: "r.\"environment\"",
|
|
19229
19235
|
status: TRACE_STATUS_SQL,
|
|
19230
19236
|
tags: "r.\"tags\""
|
|
@@ -19237,6 +19243,7 @@ const SPAN_FIELDS = {
|
|
|
19237
19243
|
startedAt: "s.\"startedAt\"",
|
|
19238
19244
|
endedAt: "s.\"endedAt\"",
|
|
19239
19245
|
durationMs: "s.\"durationMs\"",
|
|
19246
|
+
timeToFirstChunkMs: "s.\"timeToFirstChunkMs\"",
|
|
19240
19247
|
status: "s.\"status\"",
|
|
19241
19248
|
error: "s.\"error\"",
|
|
19242
19249
|
entityType: "s.\"entityType\"",
|
|
@@ -19306,6 +19313,7 @@ const TRACE_SELECT = `
|
|
|
19306
19313
|
r."resourceId" AS "resourceId",
|
|
19307
19314
|
r."startedAt" AS "startedAt",
|
|
19308
19315
|
r."endedAt" AS "endedAt",
|
|
19316
|
+
r."timeToFirstChunkMs" AS "timeToFirstChunkMs",
|
|
19309
19317
|
r."entityName" AS "entityName",
|
|
19310
19318
|
r."entityType" AS "entityType",
|
|
19311
19319
|
r."environment" AS "environment",
|
|
@@ -19429,11 +19437,11 @@ function compileScalarPredicate(predicate, registry, parameterOffset, allowMetad
|
|
|
19429
19437
|
gte: ">="
|
|
19430
19438
|
};
|
|
19431
19439
|
if (predicate.operator === "eq") return {
|
|
19432
|
-
sql: `${field} IS NOT
|
|
19440
|
+
sql: `${field} IS NOT NULL AND ${field} = ${parameter}`,
|
|
19433
19441
|
values: [...fieldValues, predicate.value]
|
|
19434
19442
|
};
|
|
19435
19443
|
if (predicate.operator === "ne") return {
|
|
19436
|
-
sql: `${field} IS
|
|
19444
|
+
sql: `${field} IS NULL OR ${field} <> ${parameter}`,
|
|
19437
19445
|
values: [...fieldValues, predicate.value]
|
|
19438
19446
|
};
|
|
19439
19447
|
const operator = operators[predicate.operator];
|
|
@@ -19522,6 +19530,8 @@ const ROOT_PUSHDOWN_FIELDS = /* @__PURE__ */ new Set([
|
|
|
19522
19530
|
"endedAt",
|
|
19523
19531
|
"entityName",
|
|
19524
19532
|
"entityType",
|
|
19533
|
+
"name",
|
|
19534
|
+
"spanType",
|
|
19525
19535
|
"environment"
|
|
19526
19536
|
]);
|
|
19527
19537
|
function isRootPushdownPredicate(predicate) {
|
|
@@ -19671,6 +19681,7 @@ function compilePostgresTraceScope(schema, selection, relationCollections, scope
|
|
|
19671
19681
|
WHEN s."isPending" THEN NULL
|
|
19672
19682
|
ELSE ${durationMsSql("s.\"startedAt\"", "s.\"endedAt\"")}
|
|
19673
19683
|
END AS "durationMs",
|
|
19684
|
+
s."timeToFirstChunkMs",
|
|
19674
19685
|
CASE WHEN s."error" IS NOT NULL THEN 'error' ELSE 'success' END AS "status",
|
|
19675
19686
|
s."error",
|
|
19676
19687
|
s."entityType",
|
|
@@ -20045,6 +20056,7 @@ function traceRowToResult(row) {
|
|
|
20045
20056
|
resourceId: row.resourceId == null ? null : String(row.resourceId),
|
|
20046
20057
|
startedAt: asIsoTimestamp$1(row.startedAt),
|
|
20047
20058
|
endedAt: asIsoTimestamp$1(row.endedAt),
|
|
20059
|
+
...timeToFirstChunkSupported && { timeToFirstChunkMs: row.timeToFirstChunkMs == null ? null : Number(row.timeToFirstChunkMs) },
|
|
20048
20060
|
entityName: row.entityName == null ? null : String(row.entityName),
|
|
20049
20061
|
entityType: row.entityType == null ? null : String(row.entityType),
|
|
20050
20062
|
environment: row.environment == null ? null : String(row.environment),
|
|
@@ -20164,6 +20176,9 @@ async function queryThreads(client, schema, plan, timeoutMs) {
|
|
|
20164
20176
|
function compileSpanQueryPredicate(predicate, offset) {
|
|
20165
20177
|
return compileScalarPredicate(predicate, SPAN_QUERY_FIELDS, offset);
|
|
20166
20178
|
}
|
|
20179
|
+
function compileThreadQueryPredicate(predicate, offset) {
|
|
20180
|
+
return compileScalarPredicate(predicate, Object.fromEntries(Object.keys(_mastra_core_storage.THREAD_QUERY_FIELD_REGISTRY).map((field) => [field, `s."${field}"`])), offset);
|
|
20181
|
+
}
|
|
20167
20182
|
//#endregion
|
|
20168
20183
|
//#region src/storage/domains/observability/v-next/span-query.ts
|
|
20169
20184
|
const identityFields = [
|
|
@@ -20197,7 +20212,8 @@ const fields = [
|
|
|
20197
20212
|
"serviceName",
|
|
20198
20213
|
"experimentId",
|
|
20199
20214
|
"environment",
|
|
20200
|
-
"executionSource"
|
|
20215
|
+
"executionSource",
|
|
20216
|
+
"timeToFirstChunkMs"
|
|
20201
20217
|
];
|
|
20202
20218
|
const identities = identityFields.map((field) => `"${field}"`).join(", ");
|
|
20203
20219
|
const identityOrder = identityFields.map((field) => `"${field}" COLLATE "C" ASC NULLS LAST`).join(", ");
|
|
@@ -20313,8 +20329,9 @@ async function querySpans(client, schema, plan, timeoutMs) {
|
|
|
20313
20329
|
return runWithPostgresTraceQueryTimeout(client, timeoutMs, async (tx) => {
|
|
20314
20330
|
const query = compilePostgresSpanQuery(schema, plan);
|
|
20315
20331
|
const rows = await tx.any(query.text, query.values);
|
|
20316
|
-
const selected = rows.map(({ version: _version, startedAt, endedAt, ...row }) => ({
|
|
20332
|
+
const selected = rows.map(({ version: _version, startedAt, endedAt, timeToFirstChunkMs, ...row }) => ({
|
|
20317
20333
|
...row,
|
|
20334
|
+
...timeToFirstChunkSupported && { timeToFirstChunkMs },
|
|
20318
20335
|
startedAt: startedAt.toISOString(),
|
|
20319
20336
|
endedAt: endedAt.toISOString()
|
|
20320
20337
|
}));
|
|
@@ -20361,11 +20378,245 @@ async function querySpans(client, schema, plan, timeoutMs) {
|
|
|
20361
20378
|
}, { repeatableRead: true });
|
|
20362
20379
|
}
|
|
20363
20380
|
//#endregion
|
|
20381
|
+
//#region src/storage/domains/observability/v-next/thread-query.ts
|
|
20382
|
+
const contextFields = [
|
|
20383
|
+
"resourceId",
|
|
20384
|
+
"userId",
|
|
20385
|
+
"entityType",
|
|
20386
|
+
"entityId",
|
|
20387
|
+
"entityName",
|
|
20388
|
+
"entityVersionId",
|
|
20389
|
+
"runId",
|
|
20390
|
+
"sessionId",
|
|
20391
|
+
"requestId",
|
|
20392
|
+
"serviceName",
|
|
20393
|
+
"experimentId",
|
|
20394
|
+
"environment",
|
|
20395
|
+
"executionSource"
|
|
20396
|
+
];
|
|
20397
|
+
function predicateFields(predicate, fields = /* @__PURE__ */ new Set()) {
|
|
20398
|
+
if (!predicate) return fields;
|
|
20399
|
+
if (predicate.type === "boolean") for (const arg of predicate.args) predicateFields(arg, fields);
|
|
20400
|
+
else if (predicate.type === "not") predicateFields(predicate.arg, fields);
|
|
20401
|
+
else fields.add(predicate.field);
|
|
20402
|
+
return fields;
|
|
20403
|
+
}
|
|
20404
|
+
function canUseThreadCandidates(probe) {
|
|
20405
|
+
return Number(probe.threadCount) <= 16384 && Number(probe.traceCount) <= 1e5 && Number(probe.threadBytes) + Number(probe.traceBytes) <= 4 * 1024 * 1024;
|
|
20406
|
+
}
|
|
20407
|
+
function compilePostgresThreadRowsQuery(schema, plan, strategy = "full") {
|
|
20408
|
+
const values = [plan.timeRange.from, plan.timeRange.to];
|
|
20409
|
+
const scope = [];
|
|
20410
|
+
if (plan.scope) {
|
|
20411
|
+
values.push(plan.scope.organizationId);
|
|
20412
|
+
scope.push(`"organizationId" = $${values.length}`);
|
|
20413
|
+
if (plan.scope.resourceId !== void 0) {
|
|
20414
|
+
values.push(plan.scope.resourceId);
|
|
20415
|
+
scope.push(`"resourceId" = $${values.length}`);
|
|
20416
|
+
}
|
|
20417
|
+
}
|
|
20418
|
+
const table = qualifiedTable(schema, TABLE_SPAN_EVENTS);
|
|
20419
|
+
const timestamp = plan.timeRange.mode === "threads" ? plan.timeRange.field : "startedAt";
|
|
20420
|
+
const identity = (field) => `"organizationId" IS NULL, COALESCE("organizationId", ''), "${field}"`;
|
|
20421
|
+
const threadFilter = `(${identity("threadId")}) IN (SELECT ${identity("threadId")} FROM candidate_threads)`;
|
|
20422
|
+
const scopedRoots = `scoped_roots AS NOT MATERIALIZED (
|
|
20423
|
+
SELECT * FROM ${table} WHERE "parentSpanId" IS NULL ${scope.length ? `AND ${scope.join(" AND ")}` : ""}
|
|
20424
|
+
)`;
|
|
20425
|
+
const candidates = `candidate_threads AS MATERIALIZED (
|
|
20426
|
+
SELECT DISTINCT "organizationId", "threadId" FROM scoped_roots
|
|
20427
|
+
WHERE "threadId" IS NOT NULL AND "${timestamp}" >= $1 AND "${timestamp}" < $2
|
|
20428
|
+
${strategy === "probe" ? "LIMIT 16385" : ""}
|
|
20429
|
+
), candidate_traces AS MATERIALIZED (
|
|
20430
|
+
SELECT DISTINCT "organizationId", "traceId" FROM scoped_roots WHERE ${threadFilter}
|
|
20431
|
+
${strategy === "probe" ? "LIMIT 100001" : ""}
|
|
20432
|
+
)`;
|
|
20433
|
+
if (strategy === "probe") return {
|
|
20434
|
+
text: `WITH ${scopedRoots}, ${candidates}
|
|
20435
|
+
SELECT (SELECT count(*) FROM candidate_threads) AS "threadCount",
|
|
20436
|
+
(SELECT COALESCE(sum(octet_length(COALESCE("organizationId", '')) + octet_length("threadId")), 0) FROM candidate_threads) AS "threadBytes",
|
|
20437
|
+
count(*) AS "traceCount", COALESCE(sum(octet_length(COALESCE("organizationId", '')) + octet_length("traceId")), 0) AS "traceBytes"
|
|
20438
|
+
FROM candidate_traces`,
|
|
20439
|
+
values
|
|
20440
|
+
};
|
|
20441
|
+
const predicate = plan.where ? compileThreadQueryPredicate(plan.where, values.length + 1) : {
|
|
20442
|
+
sql: "TRUE",
|
|
20443
|
+
values: []
|
|
20444
|
+
};
|
|
20445
|
+
values.push(...predicate.values);
|
|
20446
|
+
let after = "TRUE";
|
|
20447
|
+
if (plan.cursor) {
|
|
20448
|
+
values.push(plan.cursor.sortValue);
|
|
20449
|
+
const stamp = `$${values.length}::timestamptz`;
|
|
20450
|
+
const field = `s."${plan.orderBy.field}"`;
|
|
20451
|
+
const terms = [`${field} ${plan.orderBy.direction === "asc" ? ">" : "<"} ${stamp}`];
|
|
20452
|
+
const equal = [`${field} = ${stamp}`];
|
|
20453
|
+
for (const key of ["organizationId", "threadId"]) {
|
|
20454
|
+
const ref = `s."${key}" COLLATE "C"`;
|
|
20455
|
+
if (plan.cursor[key] === null) equal.push(`${ref} IS NULL`);
|
|
20456
|
+
else {
|
|
20457
|
+
values.push(plan.cursor[key]);
|
|
20458
|
+
const value = `$${values.length}::text COLLATE "C"`;
|
|
20459
|
+
terms.push(`(${equal.join(" AND ")} AND (${ref} > ${value} OR ${ref} IS NULL))`);
|
|
20460
|
+
equal.push(`${ref} = ${value}`);
|
|
20461
|
+
}
|
|
20462
|
+
}
|
|
20463
|
+
after = `(${terms.join(" OR ")})`;
|
|
20464
|
+
}
|
|
20465
|
+
const qualify = plan.timeRange.mode === "traces" ? "s.\"inWindow\"" : `s."${plan.timeRange.field}" >= $1 AND s."${plan.timeRange.field}" < $2`;
|
|
20466
|
+
const filtered = predicateFields(plan.where);
|
|
20467
|
+
const firstContext = [...contextFields, "timeToFirstChunkMs"].filter((field) => field === "resourceId" || filtered.has(field));
|
|
20468
|
+
const lastFields = [
|
|
20469
|
+
"traceId",
|
|
20470
|
+
"spanId",
|
|
20471
|
+
"cursorId",
|
|
20472
|
+
"resourceId",
|
|
20473
|
+
"endedAt",
|
|
20474
|
+
...filtered.has("status") ? ["status"] : []
|
|
20475
|
+
];
|
|
20476
|
+
values.push(plan.limit + 1);
|
|
20477
|
+
return {
|
|
20478
|
+
text: `WITH ${scopedRoots}, ${strategy === "candidates" ? `${candidates}, ` : ""}current_roots AS (
|
|
20479
|
+
SELECT DISTINCT ON ("organizationId", "traceId")
|
|
20480
|
+
"organizationId", "threadId", "traceId", "spanId", "cursorId", "startedAt", "endedAt", "isPending",
|
|
20481
|
+
${firstContext.map((field) => field === "timeToFirstChunkMs" ? `CASE WHEN "spanType" = 'agent_run' THEN "timeToFirstChunkMs" END AS "timeToFirstChunkMs"` : `"${field}"`).join(", ")}
|
|
20482
|
+
${filtered.has("status") ? ", CASE WHEN error IS NULL THEN 'success' ELSE 'error' END AS status" : ""}
|
|
20483
|
+
FROM scoped_roots ${strategy === "candidates" ? `WHERE (${identity("traceId")}) IN (SELECT ${identity("traceId")} FROM candidate_traces)` : ""}
|
|
20484
|
+
ORDER BY "organizationId", "traceId", "startedAt" ASC, "spanId" COLLATE "C", "cursorId" DESC
|
|
20485
|
+
), ranked AS (
|
|
20486
|
+
SELECT *, row_number() OVER first_order AS rank,
|
|
20487
|
+
max("endedAt") OVER population AS "lastActivity", count(*) OVER population AS "traceCount",
|
|
20488
|
+
bool_or("startedAt" >= $1 AND "startedAt" < $2) OVER population AS "inWindow",
|
|
20489
|
+
${lastFields.map((field) => `first_value("${field}") OVER last_order AS "last${field[0].toUpperCase()}${field.slice(1)}"`).join(", ")}
|
|
20490
|
+
FROM current_roots WHERE NOT "isPending" AND "endedAt" IS NOT NULL AND "threadId" IS NOT NULL ${strategy === "candidates" ? `AND ${threadFilter}` : ""}
|
|
20491
|
+
WINDOW population AS (PARTITION BY "organizationId", "threadId"),
|
|
20492
|
+
first_order AS (PARTITION BY "organizationId", "threadId" ORDER BY "startedAt", "traceId" COLLATE "C"),
|
|
20493
|
+
last_order AS (PARTITION BY "organizationId", "threadId" ORDER BY "startedAt" DESC, "traceId" COLLATE "C" DESC)
|
|
20494
|
+
), rows AS (
|
|
20495
|
+
SELECT "organizationId", "threadId", "traceId" AS "firstTraceId", "spanId" AS "firstSpanId", "cursorId" AS "firstCursorId",
|
|
20496
|
+
"endedAt" AS "firstEndedAt", "startedAt", "lastActivity" AS "endedAt", "traceCount", "inWindow",
|
|
20497
|
+
${firstContext.map((field) => `"${field}"`).join(", ")},
|
|
20498
|
+
${lastFields.map((field) => `"last${field[0].toUpperCase()}${field.slice(1)}"${field === "status" ? " AS status" : ""}`).join(", ")}
|
|
20499
|
+
FROM ranked WHERE rank = 1
|
|
20500
|
+
) SELECT * FROM rows s WHERE ${qualify} AND (${predicate.sql}) AND ${after}
|
|
20501
|
+
ORDER BY s."${plan.orderBy.field}" ${plan.orderBy.direction === "asc" ? "ASC" : "DESC"},
|
|
20502
|
+
s."organizationId" COLLATE "C" ASC NULLS LAST, s."threadId" COLLATE "C" ASC LIMIT $${values.length}`,
|
|
20503
|
+
values
|
|
20504
|
+
};
|
|
20505
|
+
}
|
|
20506
|
+
async function queryThreadRows(client, schema, plan, timeoutMs, strategy = "auto") {
|
|
20507
|
+
const deadline = performance.now() + _mastra_core_storage.resolveTraceQueryTimeoutMs(timeoutMs);
|
|
20508
|
+
const run = async (text, values) => {
|
|
20509
|
+
const remaining = Math.floor(deadline - performance.now());
|
|
20510
|
+
if (remaining <= 0) throw new _mastra_core_storage.TraceQueryExecutionError();
|
|
20511
|
+
return await runWithPostgresTraceQueryTimeout(client, remaining, (tx) => tx.any(text, values));
|
|
20512
|
+
};
|
|
20513
|
+
if (strategy === "auto") {
|
|
20514
|
+
const probeQuery = compilePostgresThreadRowsQuery(schema, plan, "probe");
|
|
20515
|
+
const [probe] = await run(probeQuery.text, probeQuery.values);
|
|
20516
|
+
if (Number(probe.threadCount) === 0) return {
|
|
20517
|
+
threads: [],
|
|
20518
|
+
page: { next: null }
|
|
20519
|
+
};
|
|
20520
|
+
strategy = canUseThreadCandidates(probe) ? "candidates" : "full";
|
|
20521
|
+
}
|
|
20522
|
+
const compiled = compilePostgresThreadRowsQuery(schema, plan, strategy);
|
|
20523
|
+
const selected = await run(compiled.text, compiled.values);
|
|
20524
|
+
const page = selected.slice(0, plan.limit);
|
|
20525
|
+
if (!page.length) return {
|
|
20526
|
+
threads: [],
|
|
20527
|
+
page: { next: null }
|
|
20528
|
+
};
|
|
20529
|
+
const table = qualifiedTable(schema, TABLE_SPAN_EVENTS);
|
|
20530
|
+
const values = [];
|
|
20531
|
+
const keys = page.flatMap((row) => ["first", "last"].map((which) => {
|
|
20532
|
+
const entries = {
|
|
20533
|
+
organizationId: row.organizationId,
|
|
20534
|
+
resourceId: which === "first" ? row.resourceId : row.lastResourceId,
|
|
20535
|
+
traceId: row[`${which}TraceId`],
|
|
20536
|
+
spanId: row[`${which}SpanId`],
|
|
20537
|
+
cursorId: row[`${which}CursorId`],
|
|
20538
|
+
endedAt: row[`${which}EndedAt`]
|
|
20539
|
+
};
|
|
20540
|
+
return `(${Object.entries(entries).map(([field, value]) => {
|
|
20541
|
+
values.push(value);
|
|
20542
|
+
return `"${field}" ${field === "organizationId" || field === "resourceId" ? "IS NOT DISTINCT FROM" : "="} $${values.length}`;
|
|
20543
|
+
}).join(" AND ")})`;
|
|
20544
|
+
}));
|
|
20545
|
+
const payloads = await run(`SELECT "organizationId", "traceId", "cursorId", "spanType", ${contextFields.map((field) => `"${field}"`).join(", ")},
|
|
20546
|
+
CASE WHEN "spanType" = 'agent_run' THEN "timeToFirstChunkMs" END AS "timeToFirstChunkMs",
|
|
20547
|
+
CASE WHEN error IS NULL THEN 'success' ELSE 'error' END AS status,
|
|
20548
|
+
${[
|
|
20549
|
+
"input",
|
|
20550
|
+
"output",
|
|
20551
|
+
"error"
|
|
20552
|
+
].map((field) => `"${field}Preview", CASE WHEN ${missingPreviewSql(`"${field}Preview"`)} THEN "${field}" END AS "${field}"`).join(", ")}
|
|
20553
|
+
FROM ${table} WHERE ${keys.join(" OR ")}`, values);
|
|
20554
|
+
const key = (org, trace, version) => JSON.stringify([
|
|
20555
|
+
org,
|
|
20556
|
+
trace,
|
|
20557
|
+
String(version)
|
|
20558
|
+
]);
|
|
20559
|
+
const byRoot = new Map(payloads.map((row) => [key(row.organizationId, row.traceId, row.cursorId), row]));
|
|
20560
|
+
const agents = page.filter((row) => byRoot.get(key(row.organizationId, row.firstTraceId, row.firstCursorId))?.spanType === "agent_run");
|
|
20561
|
+
const models = /* @__PURE__ */ new Map();
|
|
20562
|
+
if (agents.length) {
|
|
20563
|
+
const modelValues = [];
|
|
20564
|
+
const rows = await run(`SELECT DISTINCT ON ("organizationId", "traceId") "organizationId", "traceId",
|
|
20565
|
+
CASE WHEN jsonb_typeof(attributes -> 'model') = 'string' THEN attributes ->> 'model' END AS model,
|
|
20566
|
+
CASE WHEN jsonb_typeof(attributes -> 'provider') = 'string' THEN attributes ->> 'provider' END AS provider
|
|
20567
|
+
FROM ${table} WHERE "spanType" = 'model_generation' AND NOT "isPending" AND (${agents.map((row) => `(${Object.entries({
|
|
20568
|
+
organizationId: row.organizationId,
|
|
20569
|
+
resourceId: row.resourceId,
|
|
20570
|
+
traceId: row.firstTraceId,
|
|
20571
|
+
parentSpanId: row.firstSpanId
|
|
20572
|
+
}).map(([field, value]) => {
|
|
20573
|
+
modelValues.push(value);
|
|
20574
|
+
return `"${field}" ${field === "organizationId" || field === "resourceId" ? "IS NOT DISTINCT FROM" : "="} $${modelValues.length}`;
|
|
20575
|
+
}).join(" AND ")})`).join(" OR ")})
|
|
20576
|
+
ORDER BY "organizationId", "traceId", "startedAt", "spanId" COLLATE "C", "cursorId" DESC`, modelValues);
|
|
20577
|
+
for (const row of rows) models.set(JSON.stringify([row.organizationId, row.traceId]), row);
|
|
20578
|
+
}
|
|
20579
|
+
const threads = page.flatMap((row) => {
|
|
20580
|
+
const first = byRoot.get(key(row.organizationId, row.firstTraceId, row.firstCursorId));
|
|
20581
|
+
const last = byRoot.get(key(row.organizationId, row.lastTraceId, row.lastCursorId));
|
|
20582
|
+
if (!first || !last) return [];
|
|
20583
|
+
const model = models.get(JSON.stringify([row.organizationId, row.firstTraceId]));
|
|
20584
|
+
return [_mastra_core_storage.threadQueryRowSchema.parse({
|
|
20585
|
+
organizationId: row.organizationId,
|
|
20586
|
+
threadId: row.threadId,
|
|
20587
|
+
firstTraceId: row.firstTraceId,
|
|
20588
|
+
lastTraceId: row.lastTraceId,
|
|
20589
|
+
...Object.fromEntries(contextFields.map((field) => [field, first[field]])),
|
|
20590
|
+
status: last.status,
|
|
20591
|
+
startedAt: row.startedAt.toISOString(),
|
|
20592
|
+
endedAt: row.endedAt.toISOString(),
|
|
20593
|
+
traceCount: Number(row.traceCount),
|
|
20594
|
+
timeToFirstChunkMs: first.timeToFirstChunkMs,
|
|
20595
|
+
model: model?.model ?? null,
|
|
20596
|
+
provider: model?.provider ?? null,
|
|
20597
|
+
inputPreview: readPreview(first.inputPreview, first.input),
|
|
20598
|
+
outputPreview: readPreview(last.outputPreview, last.output),
|
|
20599
|
+
errorPreview: readPreview(last.errorPreview, last.error)
|
|
20600
|
+
})];
|
|
20601
|
+
});
|
|
20602
|
+
const last = page.at(-1);
|
|
20603
|
+
return {
|
|
20604
|
+
threads,
|
|
20605
|
+
page: { next: selected.length > plan.limit ? _mastra_core_storage.encodeThreadQueryCursor(plan, {
|
|
20606
|
+
organizationId: last.organizationId,
|
|
20607
|
+
threadId: last.threadId,
|
|
20608
|
+
sortValue: last[plan.orderBy.field].toISOString()
|
|
20609
|
+
}) : null }
|
|
20610
|
+
};
|
|
20611
|
+
}
|
|
20612
|
+
//#endregion
|
|
20364
20613
|
//#region src/storage/domains/observability/v-next/trace-aggregate.ts
|
|
20365
20614
|
/** Trace-root column expressions (alias `r`) for each groupable dimension; same values `where` sees. */
|
|
20366
20615
|
const DIMENSION_SQL = {
|
|
20367
20616
|
entityType: "r.\"entityType\"",
|
|
20368
20617
|
entityName: "r.\"entityName\"",
|
|
20618
|
+
name: "r.\"name\"",
|
|
20619
|
+
spanType: "r.\"spanType\"",
|
|
20369
20620
|
environment: "r.\"environment\"",
|
|
20370
20621
|
status: TRACE_STATUS_SQL,
|
|
20371
20622
|
serviceName: "r.\"serviceName\"",
|
|
@@ -21592,12 +21843,15 @@ var ObservabilityStoragePostgresVNext = class ObservabilityStoragePostgresVNext
|
|
|
21592
21843
|
"trace-query",
|
|
21593
21844
|
"trace-aggregate",
|
|
21594
21845
|
...spanQueryFeatures,
|
|
21846
|
+
...typeof _mastra_core_storage.planThreadRowsQuery === "function" ? ["thread-query-rows"] : [],
|
|
21595
21847
|
"trace-query-root-duration",
|
|
21596
21848
|
"trace-query-discovery",
|
|
21597
21849
|
"thread-query",
|
|
21598
21850
|
"trace-query-tenant-scope",
|
|
21599
21851
|
"feedback",
|
|
21600
|
-
"trace-query-context-ids"
|
|
21852
|
+
"trace-query-context-ids",
|
|
21853
|
+
...timeToFirstChunkFeatures,
|
|
21854
|
+
"trace-query-root-span-fields"
|
|
21601
21855
|
];
|
|
21602
21856
|
return [
|
|
21603
21857
|
"metrics",
|
|
@@ -21612,12 +21866,15 @@ var ObservabilityStoragePostgresVNext = class ObservabilityStoragePostgresVNext
|
|
|
21612
21866
|
"trace-query",
|
|
21613
21867
|
"trace-aggregate",
|
|
21614
21868
|
...spanQueryFeatures,
|
|
21869
|
+
...typeof _mastra_core_storage.planThreadRowsQuery === "function" ? ["thread-query-rows"] : [],
|
|
21615
21870
|
"trace-query-root-duration",
|
|
21616
21871
|
"trace-query-discovery",
|
|
21617
21872
|
"thread-query",
|
|
21618
21873
|
"trace-query-tenant-scope",
|
|
21619
21874
|
"feedback",
|
|
21620
|
-
"trace-query-context-ids"
|
|
21875
|
+
"trace-query-context-ids",
|
|
21876
|
+
...timeToFirstChunkFeatures,
|
|
21877
|
+
"trace-query-root-span-fields"
|
|
21621
21878
|
];
|
|
21622
21879
|
}
|
|
21623
21880
|
async #run(op, fn, details) {
|
|
@@ -21679,7 +21936,7 @@ var ObservabilityStoragePostgresVNext = class ObservabilityStoragePostgresVNext
|
|
|
21679
21936
|
return this.#run("GET_TRACE_QUERY_VALUES", () => getTraceQueryValues(this.#readClient, this.#schema, plan, this.#traceQueryTimeoutMs));
|
|
21680
21937
|
}
|
|
21681
21938
|
async queryThreads(plan) {
|
|
21682
|
-
return this.#run("QUERY_THREADS", () => queryThreads(this.#readClient, this.#schema, plan, this.#traceQueryTimeoutMs));
|
|
21939
|
+
return this.#run("QUERY_THREADS", () => plan.result === "threadRows" ? queryThreadRows(this.#readClient, this.#schema, plan, this.#traceQueryTimeoutMs) : queryThreads(this.#readClient, this.#schema, plan, this.#traceQueryTimeoutMs));
|
|
21683
21940
|
}
|
|
21684
21941
|
async listBranches(args) {
|
|
21685
21942
|
return this.#run("LIST_BRANCHES", () => listBranches(this.#readClient, this.#schema, args));
|
|
@@ -24111,7 +24368,7 @@ var SkillsPG = class SkillsPG extends _mastra_core_storage.SkillsStorage {
|
|
|
24111
24368
|
}
|
|
24112
24369
|
}
|
|
24113
24370
|
async list(args) {
|
|
24114
|
-
const { page = 0, perPage: perPageInput, orderBy, authorId, visibility, status, entityIds, pinFavoritedFor, favoritedOnly } = args || {};
|
|
24371
|
+
const { page = 0, perPage: perPageInput, orderBy, authorId, visibility, status, entityIds, pinFavoritedFor, favoritedOnly, metadata } = args || {};
|
|
24115
24372
|
const { field, direction } = this.parseOrderBy(orderBy);
|
|
24116
24373
|
if (page < 0) throw new _mastra_core_error.MastraError({
|
|
24117
24374
|
id: (0, _mastra_core_storage.createStorageErrorId)("PG", "LIST_SKILLS", "INVALID_PAGE"),
|
|
@@ -24156,6 +24413,16 @@ var SkillsPG = class SkillsPG extends _mastra_core_storage.SkillsStorage {
|
|
|
24156
24413
|
conditions.push(`s.visibility = $${paramIdx++}`);
|
|
24157
24414
|
queryParams.push(visibility);
|
|
24158
24415
|
}
|
|
24416
|
+
if (metadata && Object.keys(metadata).length > 0) {
|
|
24417
|
+
const versionsTable = getTableName$5({
|
|
24418
|
+
indexName: _mastra_core_storage.TABLE_SKILL_VERSIONS,
|
|
24419
|
+
schemaName: getSchemaName$5(this.#schema)
|
|
24420
|
+
});
|
|
24421
|
+
const latestVersionId = `(SELECT lv.id FROM ${versionsTable} lv WHERE lv."skillId" = s.id ORDER BY lv."versionNumber" DESC LIMIT 1)`;
|
|
24422
|
+
const resolvedVersionId = status === "draft" ? latestVersionId : `COALESCE(s."activeVersionId", ${latestVersionId})`;
|
|
24423
|
+
conditions.push(`EXISTS (SELECT 1 FROM ${versionsTable} mv WHERE mv."skillId" = s.id AND mv.id = ${resolvedVersionId} AND mv.metadata @> $${paramIdx++}::jsonb)`);
|
|
24424
|
+
queryParams.push(toPgJson(metadata));
|
|
24425
|
+
}
|
|
24159
24426
|
if (entityIds && entityIds.length > 0) {
|
|
24160
24427
|
const placeholders = entityIds.map(() => `$${paramIdx++}`).join(", ");
|
|
24161
24428
|
conditions.push(`s.id IN (${placeholders})`);
|