@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/index.js
CHANGED
|
@@ -19185,6 +19185,9 @@ async function getScorePercentiles(client, schema, args) {
|
|
|
19185
19185
|
//#endregion
|
|
19186
19186
|
//#region src/storage/domains/observability/v-next/trace-query.ts
|
|
19187
19187
|
const TRACE_STATUS_SQL = `CASE WHEN r."error" IS NOT NULL THEN 'error' ELSE 'success' END`;
|
|
19188
|
+
/** Core versions without the field reject it in strict query results, so it is only returned when core knows it. */
|
|
19189
|
+
const timeToFirstChunkSupported = "timeToFirstChunkMs" in coreStorage.TRACE_QUERY_FIELD_REGISTRY.trace;
|
|
19190
|
+
const timeToFirstChunkFeatures = timeToFirstChunkSupported ? ["trace-query-time-to-first-chunk"] : [];
|
|
19188
19191
|
function durationMsSql(startedAt, endedAt) {
|
|
19189
19192
|
return `EXTRACT(EPOCH FROM (${endedAt} - ${startedAt}))::numeric * 1000`;
|
|
19190
19193
|
}
|
|
@@ -19199,8 +19202,11 @@ const TRACE_FIELDS = {
|
|
|
19199
19202
|
startedAt: "r.\"startedAt\"",
|
|
19200
19203
|
endedAt: "r.\"endedAt\"",
|
|
19201
19204
|
durationMs: durationMsSql("r.\"startedAt\"", "r.\"endedAt\""),
|
|
19205
|
+
timeToFirstChunkMs: "r.\"timeToFirstChunkMs\"",
|
|
19202
19206
|
entityName: "r.\"entityName\"",
|
|
19203
19207
|
entityType: "r.\"entityType\"",
|
|
19208
|
+
name: "r.\"name\"",
|
|
19209
|
+
spanType: "r.\"spanType\"",
|
|
19204
19210
|
environment: "r.\"environment\"",
|
|
19205
19211
|
status: TRACE_STATUS_SQL,
|
|
19206
19212
|
tags: "r.\"tags\""
|
|
@@ -19213,6 +19219,7 @@ const SPAN_FIELDS = {
|
|
|
19213
19219
|
startedAt: "s.\"startedAt\"",
|
|
19214
19220
|
endedAt: "s.\"endedAt\"",
|
|
19215
19221
|
durationMs: "s.\"durationMs\"",
|
|
19222
|
+
timeToFirstChunkMs: "s.\"timeToFirstChunkMs\"",
|
|
19216
19223
|
status: "s.\"status\"",
|
|
19217
19224
|
error: "s.\"error\"",
|
|
19218
19225
|
entityType: "s.\"entityType\"",
|
|
@@ -19282,6 +19289,7 @@ const TRACE_SELECT = `
|
|
|
19282
19289
|
r."resourceId" AS "resourceId",
|
|
19283
19290
|
r."startedAt" AS "startedAt",
|
|
19284
19291
|
r."endedAt" AS "endedAt",
|
|
19292
|
+
r."timeToFirstChunkMs" AS "timeToFirstChunkMs",
|
|
19285
19293
|
r."entityName" AS "entityName",
|
|
19286
19294
|
r."entityType" AS "entityType",
|
|
19287
19295
|
r."environment" AS "environment",
|
|
@@ -19405,11 +19413,11 @@ function compileScalarPredicate(predicate, registry, parameterOffset, allowMetad
|
|
|
19405
19413
|
gte: ">="
|
|
19406
19414
|
};
|
|
19407
19415
|
if (predicate.operator === "eq") return {
|
|
19408
|
-
sql: `${field} IS NOT
|
|
19416
|
+
sql: `${field} IS NOT NULL AND ${field} = ${parameter}`,
|
|
19409
19417
|
values: [...fieldValues, predicate.value]
|
|
19410
19418
|
};
|
|
19411
19419
|
if (predicate.operator === "ne") return {
|
|
19412
|
-
sql: `${field} IS
|
|
19420
|
+
sql: `${field} IS NULL OR ${field} <> ${parameter}`,
|
|
19413
19421
|
values: [...fieldValues, predicate.value]
|
|
19414
19422
|
};
|
|
19415
19423
|
const operator = operators[predicate.operator];
|
|
@@ -19498,6 +19506,8 @@ const ROOT_PUSHDOWN_FIELDS = /* @__PURE__ */ new Set([
|
|
|
19498
19506
|
"endedAt",
|
|
19499
19507
|
"entityName",
|
|
19500
19508
|
"entityType",
|
|
19509
|
+
"name",
|
|
19510
|
+
"spanType",
|
|
19501
19511
|
"environment"
|
|
19502
19512
|
]);
|
|
19503
19513
|
function isRootPushdownPredicate(predicate) {
|
|
@@ -19647,6 +19657,7 @@ function compilePostgresTraceScope(schema, selection, relationCollections, scope
|
|
|
19647
19657
|
WHEN s."isPending" THEN NULL
|
|
19648
19658
|
ELSE ${durationMsSql("s.\"startedAt\"", "s.\"endedAt\"")}
|
|
19649
19659
|
END AS "durationMs",
|
|
19660
|
+
s."timeToFirstChunkMs",
|
|
19650
19661
|
CASE WHEN s."error" IS NOT NULL THEN 'error' ELSE 'success' END AS "status",
|
|
19651
19662
|
s."error",
|
|
19652
19663
|
s."entityType",
|
|
@@ -20021,6 +20032,7 @@ function traceRowToResult(row) {
|
|
|
20021
20032
|
resourceId: row.resourceId == null ? null : String(row.resourceId),
|
|
20022
20033
|
startedAt: asIsoTimestamp$1(row.startedAt),
|
|
20023
20034
|
endedAt: asIsoTimestamp$1(row.endedAt),
|
|
20035
|
+
...timeToFirstChunkSupported && { timeToFirstChunkMs: row.timeToFirstChunkMs == null ? null : Number(row.timeToFirstChunkMs) },
|
|
20024
20036
|
entityName: row.entityName == null ? null : String(row.entityName),
|
|
20025
20037
|
entityType: row.entityType == null ? null : String(row.entityType),
|
|
20026
20038
|
environment: row.environment == null ? null : String(row.environment),
|
|
@@ -20140,6 +20152,9 @@ async function queryThreads(client, schema, plan, timeoutMs) {
|
|
|
20140
20152
|
function compileSpanQueryPredicate(predicate, offset) {
|
|
20141
20153
|
return compileScalarPredicate(predicate, SPAN_QUERY_FIELDS, offset);
|
|
20142
20154
|
}
|
|
20155
|
+
function compileThreadQueryPredicate(predicate, offset) {
|
|
20156
|
+
return compileScalarPredicate(predicate, Object.fromEntries(Object.keys(coreStorage.THREAD_QUERY_FIELD_REGISTRY).map((field) => [field, `s."${field}"`])), offset);
|
|
20157
|
+
}
|
|
20143
20158
|
//#endregion
|
|
20144
20159
|
//#region src/storage/domains/observability/v-next/span-query.ts
|
|
20145
20160
|
const identityFields = [
|
|
@@ -20173,7 +20188,8 @@ const fields = [
|
|
|
20173
20188
|
"serviceName",
|
|
20174
20189
|
"experimentId",
|
|
20175
20190
|
"environment",
|
|
20176
|
-
"executionSource"
|
|
20191
|
+
"executionSource",
|
|
20192
|
+
"timeToFirstChunkMs"
|
|
20177
20193
|
];
|
|
20178
20194
|
const identities = identityFields.map((field) => `"${field}"`).join(", ");
|
|
20179
20195
|
const identityOrder = identityFields.map((field) => `"${field}" COLLATE "C" ASC NULLS LAST`).join(", ");
|
|
@@ -20289,8 +20305,9 @@ async function querySpans(client, schema, plan, timeoutMs) {
|
|
|
20289
20305
|
return runWithPostgresTraceQueryTimeout(client, timeoutMs, async (tx) => {
|
|
20290
20306
|
const query = compilePostgresSpanQuery(schema, plan);
|
|
20291
20307
|
const rows = await tx.any(query.text, query.values);
|
|
20292
|
-
const selected = rows.map(({ version: _version, startedAt, endedAt, ...row }) => ({
|
|
20308
|
+
const selected = rows.map(({ version: _version, startedAt, endedAt, timeToFirstChunkMs, ...row }) => ({
|
|
20293
20309
|
...row,
|
|
20310
|
+
...timeToFirstChunkSupported && { timeToFirstChunkMs },
|
|
20294
20311
|
startedAt: startedAt.toISOString(),
|
|
20295
20312
|
endedAt: endedAt.toISOString()
|
|
20296
20313
|
}));
|
|
@@ -20337,11 +20354,245 @@ async function querySpans(client, schema, plan, timeoutMs) {
|
|
|
20337
20354
|
}, { repeatableRead: true });
|
|
20338
20355
|
}
|
|
20339
20356
|
//#endregion
|
|
20357
|
+
//#region src/storage/domains/observability/v-next/thread-query.ts
|
|
20358
|
+
const contextFields = [
|
|
20359
|
+
"resourceId",
|
|
20360
|
+
"userId",
|
|
20361
|
+
"entityType",
|
|
20362
|
+
"entityId",
|
|
20363
|
+
"entityName",
|
|
20364
|
+
"entityVersionId",
|
|
20365
|
+
"runId",
|
|
20366
|
+
"sessionId",
|
|
20367
|
+
"requestId",
|
|
20368
|
+
"serviceName",
|
|
20369
|
+
"experimentId",
|
|
20370
|
+
"environment",
|
|
20371
|
+
"executionSource"
|
|
20372
|
+
];
|
|
20373
|
+
function predicateFields(predicate, fields = /* @__PURE__ */ new Set()) {
|
|
20374
|
+
if (!predicate) return fields;
|
|
20375
|
+
if (predicate.type === "boolean") for (const arg of predicate.args) predicateFields(arg, fields);
|
|
20376
|
+
else if (predicate.type === "not") predicateFields(predicate.arg, fields);
|
|
20377
|
+
else fields.add(predicate.field);
|
|
20378
|
+
return fields;
|
|
20379
|
+
}
|
|
20380
|
+
function canUseThreadCandidates(probe) {
|
|
20381
|
+
return Number(probe.threadCount) <= 16384 && Number(probe.traceCount) <= 1e5 && Number(probe.threadBytes) + Number(probe.traceBytes) <= 4 * 1024 * 1024;
|
|
20382
|
+
}
|
|
20383
|
+
function compilePostgresThreadRowsQuery(schema, plan, strategy = "full") {
|
|
20384
|
+
const values = [plan.timeRange.from, plan.timeRange.to];
|
|
20385
|
+
const scope = [];
|
|
20386
|
+
if (plan.scope) {
|
|
20387
|
+
values.push(plan.scope.organizationId);
|
|
20388
|
+
scope.push(`"organizationId" = $${values.length}`);
|
|
20389
|
+
if (plan.scope.resourceId !== void 0) {
|
|
20390
|
+
values.push(plan.scope.resourceId);
|
|
20391
|
+
scope.push(`"resourceId" = $${values.length}`);
|
|
20392
|
+
}
|
|
20393
|
+
}
|
|
20394
|
+
const table = qualifiedTable(schema, TABLE_SPAN_EVENTS);
|
|
20395
|
+
const timestamp = plan.timeRange.mode === "threads" ? plan.timeRange.field : "startedAt";
|
|
20396
|
+
const identity = (field) => `"organizationId" IS NULL, COALESCE("organizationId", ''), "${field}"`;
|
|
20397
|
+
const threadFilter = `(${identity("threadId")}) IN (SELECT ${identity("threadId")} FROM candidate_threads)`;
|
|
20398
|
+
const scopedRoots = `scoped_roots AS NOT MATERIALIZED (
|
|
20399
|
+
SELECT * FROM ${table} WHERE "parentSpanId" IS NULL ${scope.length ? `AND ${scope.join(" AND ")}` : ""}
|
|
20400
|
+
)`;
|
|
20401
|
+
const candidates = `candidate_threads AS MATERIALIZED (
|
|
20402
|
+
SELECT DISTINCT "organizationId", "threadId" FROM scoped_roots
|
|
20403
|
+
WHERE "threadId" IS NOT NULL AND "${timestamp}" >= $1 AND "${timestamp}" < $2
|
|
20404
|
+
${strategy === "probe" ? "LIMIT 16385" : ""}
|
|
20405
|
+
), candidate_traces AS MATERIALIZED (
|
|
20406
|
+
SELECT DISTINCT "organizationId", "traceId" FROM scoped_roots WHERE ${threadFilter}
|
|
20407
|
+
${strategy === "probe" ? "LIMIT 100001" : ""}
|
|
20408
|
+
)`;
|
|
20409
|
+
if (strategy === "probe") return {
|
|
20410
|
+
text: `WITH ${scopedRoots}, ${candidates}
|
|
20411
|
+
SELECT (SELECT count(*) FROM candidate_threads) AS "threadCount",
|
|
20412
|
+
(SELECT COALESCE(sum(octet_length(COALESCE("organizationId", '')) + octet_length("threadId")), 0) FROM candidate_threads) AS "threadBytes",
|
|
20413
|
+
count(*) AS "traceCount", COALESCE(sum(octet_length(COALESCE("organizationId", '')) + octet_length("traceId")), 0) AS "traceBytes"
|
|
20414
|
+
FROM candidate_traces`,
|
|
20415
|
+
values
|
|
20416
|
+
};
|
|
20417
|
+
const predicate = plan.where ? compileThreadQueryPredicate(plan.where, values.length + 1) : {
|
|
20418
|
+
sql: "TRUE",
|
|
20419
|
+
values: []
|
|
20420
|
+
};
|
|
20421
|
+
values.push(...predicate.values);
|
|
20422
|
+
let after = "TRUE";
|
|
20423
|
+
if (plan.cursor) {
|
|
20424
|
+
values.push(plan.cursor.sortValue);
|
|
20425
|
+
const stamp = `$${values.length}::timestamptz`;
|
|
20426
|
+
const field = `s."${plan.orderBy.field}"`;
|
|
20427
|
+
const terms = [`${field} ${plan.orderBy.direction === "asc" ? ">" : "<"} ${stamp}`];
|
|
20428
|
+
const equal = [`${field} = ${stamp}`];
|
|
20429
|
+
for (const key of ["organizationId", "threadId"]) {
|
|
20430
|
+
const ref = `s."${key}" COLLATE "C"`;
|
|
20431
|
+
if (plan.cursor[key] === null) equal.push(`${ref} IS NULL`);
|
|
20432
|
+
else {
|
|
20433
|
+
values.push(plan.cursor[key]);
|
|
20434
|
+
const value = `$${values.length}::text COLLATE "C"`;
|
|
20435
|
+
terms.push(`(${equal.join(" AND ")} AND (${ref} > ${value} OR ${ref} IS NULL))`);
|
|
20436
|
+
equal.push(`${ref} = ${value}`);
|
|
20437
|
+
}
|
|
20438
|
+
}
|
|
20439
|
+
after = `(${terms.join(" OR ")})`;
|
|
20440
|
+
}
|
|
20441
|
+
const qualify = plan.timeRange.mode === "traces" ? "s.\"inWindow\"" : `s."${plan.timeRange.field}" >= $1 AND s."${plan.timeRange.field}" < $2`;
|
|
20442
|
+
const filtered = predicateFields(plan.where);
|
|
20443
|
+
const firstContext = [...contextFields, "timeToFirstChunkMs"].filter((field) => field === "resourceId" || filtered.has(field));
|
|
20444
|
+
const lastFields = [
|
|
20445
|
+
"traceId",
|
|
20446
|
+
"spanId",
|
|
20447
|
+
"cursorId",
|
|
20448
|
+
"resourceId",
|
|
20449
|
+
"endedAt",
|
|
20450
|
+
...filtered.has("status") ? ["status"] : []
|
|
20451
|
+
];
|
|
20452
|
+
values.push(plan.limit + 1);
|
|
20453
|
+
return {
|
|
20454
|
+
text: `WITH ${scopedRoots}, ${strategy === "candidates" ? `${candidates}, ` : ""}current_roots AS (
|
|
20455
|
+
SELECT DISTINCT ON ("organizationId", "traceId")
|
|
20456
|
+
"organizationId", "threadId", "traceId", "spanId", "cursorId", "startedAt", "endedAt", "isPending",
|
|
20457
|
+
${firstContext.map((field) => field === "timeToFirstChunkMs" ? `CASE WHEN "spanType" = 'agent_run' THEN "timeToFirstChunkMs" END AS "timeToFirstChunkMs"` : `"${field}"`).join(", ")}
|
|
20458
|
+
${filtered.has("status") ? ", CASE WHEN error IS NULL THEN 'success' ELSE 'error' END AS status" : ""}
|
|
20459
|
+
FROM scoped_roots ${strategy === "candidates" ? `WHERE (${identity("traceId")}) IN (SELECT ${identity("traceId")} FROM candidate_traces)` : ""}
|
|
20460
|
+
ORDER BY "organizationId", "traceId", "startedAt" ASC, "spanId" COLLATE "C", "cursorId" DESC
|
|
20461
|
+
), ranked AS (
|
|
20462
|
+
SELECT *, row_number() OVER first_order AS rank,
|
|
20463
|
+
max("endedAt") OVER population AS "lastActivity", count(*) OVER population AS "traceCount",
|
|
20464
|
+
bool_or("startedAt" >= $1 AND "startedAt" < $2) OVER population AS "inWindow",
|
|
20465
|
+
${lastFields.map((field) => `first_value("${field}") OVER last_order AS "last${field[0].toUpperCase()}${field.slice(1)}"`).join(", ")}
|
|
20466
|
+
FROM current_roots WHERE NOT "isPending" AND "endedAt" IS NOT NULL AND "threadId" IS NOT NULL ${strategy === "candidates" ? `AND ${threadFilter}` : ""}
|
|
20467
|
+
WINDOW population AS (PARTITION BY "organizationId", "threadId"),
|
|
20468
|
+
first_order AS (PARTITION BY "organizationId", "threadId" ORDER BY "startedAt", "traceId" COLLATE "C"),
|
|
20469
|
+
last_order AS (PARTITION BY "organizationId", "threadId" ORDER BY "startedAt" DESC, "traceId" COLLATE "C" DESC)
|
|
20470
|
+
), rows AS (
|
|
20471
|
+
SELECT "organizationId", "threadId", "traceId" AS "firstTraceId", "spanId" AS "firstSpanId", "cursorId" AS "firstCursorId",
|
|
20472
|
+
"endedAt" AS "firstEndedAt", "startedAt", "lastActivity" AS "endedAt", "traceCount", "inWindow",
|
|
20473
|
+
${firstContext.map((field) => `"${field}"`).join(", ")},
|
|
20474
|
+
${lastFields.map((field) => `"last${field[0].toUpperCase()}${field.slice(1)}"${field === "status" ? " AS status" : ""}`).join(", ")}
|
|
20475
|
+
FROM ranked WHERE rank = 1
|
|
20476
|
+
) SELECT * FROM rows s WHERE ${qualify} AND (${predicate.sql}) AND ${after}
|
|
20477
|
+
ORDER BY s."${plan.orderBy.field}" ${plan.orderBy.direction === "asc" ? "ASC" : "DESC"},
|
|
20478
|
+
s."organizationId" COLLATE "C" ASC NULLS LAST, s."threadId" COLLATE "C" ASC LIMIT $${values.length}`,
|
|
20479
|
+
values
|
|
20480
|
+
};
|
|
20481
|
+
}
|
|
20482
|
+
async function queryThreadRows(client, schema, plan, timeoutMs, strategy = "auto") {
|
|
20483
|
+
const deadline = performance.now() + coreStorage.resolveTraceQueryTimeoutMs(timeoutMs);
|
|
20484
|
+
const run = async (text, values) => {
|
|
20485
|
+
const remaining = Math.floor(deadline - performance.now());
|
|
20486
|
+
if (remaining <= 0) throw new coreStorage.TraceQueryExecutionError();
|
|
20487
|
+
return await runWithPostgresTraceQueryTimeout(client, remaining, (tx) => tx.any(text, values));
|
|
20488
|
+
};
|
|
20489
|
+
if (strategy === "auto") {
|
|
20490
|
+
const probeQuery = compilePostgresThreadRowsQuery(schema, plan, "probe");
|
|
20491
|
+
const [probe] = await run(probeQuery.text, probeQuery.values);
|
|
20492
|
+
if (Number(probe.threadCount) === 0) return {
|
|
20493
|
+
threads: [],
|
|
20494
|
+
page: { next: null }
|
|
20495
|
+
};
|
|
20496
|
+
strategy = canUseThreadCandidates(probe) ? "candidates" : "full";
|
|
20497
|
+
}
|
|
20498
|
+
const compiled = compilePostgresThreadRowsQuery(schema, plan, strategy);
|
|
20499
|
+
const selected = await run(compiled.text, compiled.values);
|
|
20500
|
+
const page = selected.slice(0, plan.limit);
|
|
20501
|
+
if (!page.length) return {
|
|
20502
|
+
threads: [],
|
|
20503
|
+
page: { next: null }
|
|
20504
|
+
};
|
|
20505
|
+
const table = qualifiedTable(schema, TABLE_SPAN_EVENTS);
|
|
20506
|
+
const values = [];
|
|
20507
|
+
const keys = page.flatMap((row) => ["first", "last"].map((which) => {
|
|
20508
|
+
const entries = {
|
|
20509
|
+
organizationId: row.organizationId,
|
|
20510
|
+
resourceId: which === "first" ? row.resourceId : row.lastResourceId,
|
|
20511
|
+
traceId: row[`${which}TraceId`],
|
|
20512
|
+
spanId: row[`${which}SpanId`],
|
|
20513
|
+
cursorId: row[`${which}CursorId`],
|
|
20514
|
+
endedAt: row[`${which}EndedAt`]
|
|
20515
|
+
};
|
|
20516
|
+
return `(${Object.entries(entries).map(([field, value]) => {
|
|
20517
|
+
values.push(value);
|
|
20518
|
+
return `"${field}" ${field === "organizationId" || field === "resourceId" ? "IS NOT DISTINCT FROM" : "="} $${values.length}`;
|
|
20519
|
+
}).join(" AND ")})`;
|
|
20520
|
+
}));
|
|
20521
|
+
const payloads = await run(`SELECT "organizationId", "traceId", "cursorId", "spanType", ${contextFields.map((field) => `"${field}"`).join(", ")},
|
|
20522
|
+
CASE WHEN "spanType" = 'agent_run' THEN "timeToFirstChunkMs" END AS "timeToFirstChunkMs",
|
|
20523
|
+
CASE WHEN error IS NULL THEN 'success' ELSE 'error' END AS status,
|
|
20524
|
+
${[
|
|
20525
|
+
"input",
|
|
20526
|
+
"output",
|
|
20527
|
+
"error"
|
|
20528
|
+
].map((field) => `"${field}Preview", CASE WHEN ${missingPreviewSql(`"${field}Preview"`)} THEN "${field}" END AS "${field}"`).join(", ")}
|
|
20529
|
+
FROM ${table} WHERE ${keys.join(" OR ")}`, values);
|
|
20530
|
+
const key = (org, trace, version) => JSON.stringify([
|
|
20531
|
+
org,
|
|
20532
|
+
trace,
|
|
20533
|
+
String(version)
|
|
20534
|
+
]);
|
|
20535
|
+
const byRoot = new Map(payloads.map((row) => [key(row.organizationId, row.traceId, row.cursorId), row]));
|
|
20536
|
+
const agents = page.filter((row) => byRoot.get(key(row.organizationId, row.firstTraceId, row.firstCursorId))?.spanType === "agent_run");
|
|
20537
|
+
const models = /* @__PURE__ */ new Map();
|
|
20538
|
+
if (agents.length) {
|
|
20539
|
+
const modelValues = [];
|
|
20540
|
+
const rows = await run(`SELECT DISTINCT ON ("organizationId", "traceId") "organizationId", "traceId",
|
|
20541
|
+
CASE WHEN jsonb_typeof(attributes -> 'model') = 'string' THEN attributes ->> 'model' END AS model,
|
|
20542
|
+
CASE WHEN jsonb_typeof(attributes -> 'provider') = 'string' THEN attributes ->> 'provider' END AS provider
|
|
20543
|
+
FROM ${table} WHERE "spanType" = 'model_generation' AND NOT "isPending" AND (${agents.map((row) => `(${Object.entries({
|
|
20544
|
+
organizationId: row.organizationId,
|
|
20545
|
+
resourceId: row.resourceId,
|
|
20546
|
+
traceId: row.firstTraceId,
|
|
20547
|
+
parentSpanId: row.firstSpanId
|
|
20548
|
+
}).map(([field, value]) => {
|
|
20549
|
+
modelValues.push(value);
|
|
20550
|
+
return `"${field}" ${field === "organizationId" || field === "resourceId" ? "IS NOT DISTINCT FROM" : "="} $${modelValues.length}`;
|
|
20551
|
+
}).join(" AND ")})`).join(" OR ")})
|
|
20552
|
+
ORDER BY "organizationId", "traceId", "startedAt", "spanId" COLLATE "C", "cursorId" DESC`, modelValues);
|
|
20553
|
+
for (const row of rows) models.set(JSON.stringify([row.organizationId, row.traceId]), row);
|
|
20554
|
+
}
|
|
20555
|
+
const threads = page.flatMap((row) => {
|
|
20556
|
+
const first = byRoot.get(key(row.organizationId, row.firstTraceId, row.firstCursorId));
|
|
20557
|
+
const last = byRoot.get(key(row.organizationId, row.lastTraceId, row.lastCursorId));
|
|
20558
|
+
if (!first || !last) return [];
|
|
20559
|
+
const model = models.get(JSON.stringify([row.organizationId, row.firstTraceId]));
|
|
20560
|
+
return [coreStorage.threadQueryRowSchema.parse({
|
|
20561
|
+
organizationId: row.organizationId,
|
|
20562
|
+
threadId: row.threadId,
|
|
20563
|
+
firstTraceId: row.firstTraceId,
|
|
20564
|
+
lastTraceId: row.lastTraceId,
|
|
20565
|
+
...Object.fromEntries(contextFields.map((field) => [field, first[field]])),
|
|
20566
|
+
status: last.status,
|
|
20567
|
+
startedAt: row.startedAt.toISOString(),
|
|
20568
|
+
endedAt: row.endedAt.toISOString(),
|
|
20569
|
+
traceCount: Number(row.traceCount),
|
|
20570
|
+
timeToFirstChunkMs: first.timeToFirstChunkMs,
|
|
20571
|
+
model: model?.model ?? null,
|
|
20572
|
+
provider: model?.provider ?? null,
|
|
20573
|
+
inputPreview: readPreview(first.inputPreview, first.input),
|
|
20574
|
+
outputPreview: readPreview(last.outputPreview, last.output),
|
|
20575
|
+
errorPreview: readPreview(last.errorPreview, last.error)
|
|
20576
|
+
})];
|
|
20577
|
+
});
|
|
20578
|
+
const last = page.at(-1);
|
|
20579
|
+
return {
|
|
20580
|
+
threads,
|
|
20581
|
+
page: { next: selected.length > plan.limit ? coreStorage.encodeThreadQueryCursor(plan, {
|
|
20582
|
+
organizationId: last.organizationId,
|
|
20583
|
+
threadId: last.threadId,
|
|
20584
|
+
sortValue: last[plan.orderBy.field].toISOString()
|
|
20585
|
+
}) : null }
|
|
20586
|
+
};
|
|
20587
|
+
}
|
|
20588
|
+
//#endregion
|
|
20340
20589
|
//#region src/storage/domains/observability/v-next/trace-aggregate.ts
|
|
20341
20590
|
/** Trace-root column expressions (alias `r`) for each groupable dimension; same values `where` sees. */
|
|
20342
20591
|
const DIMENSION_SQL = {
|
|
20343
20592
|
entityType: "r.\"entityType\"",
|
|
20344
20593
|
entityName: "r.\"entityName\"",
|
|
20594
|
+
name: "r.\"name\"",
|
|
20595
|
+
spanType: "r.\"spanType\"",
|
|
20345
20596
|
environment: "r.\"environment\"",
|
|
20346
20597
|
status: TRACE_STATUS_SQL,
|
|
20347
20598
|
serviceName: "r.\"serviceName\"",
|
|
@@ -21568,12 +21819,15 @@ var ObservabilityStoragePostgresVNext = class ObservabilityStoragePostgresVNext
|
|
|
21568
21819
|
"trace-query",
|
|
21569
21820
|
"trace-aggregate",
|
|
21570
21821
|
...spanQueryFeatures,
|
|
21822
|
+
...typeof coreStorage.planThreadRowsQuery === "function" ? ["thread-query-rows"] : [],
|
|
21571
21823
|
"trace-query-root-duration",
|
|
21572
21824
|
"trace-query-discovery",
|
|
21573
21825
|
"thread-query",
|
|
21574
21826
|
"trace-query-tenant-scope",
|
|
21575
21827
|
"feedback",
|
|
21576
|
-
"trace-query-context-ids"
|
|
21828
|
+
"trace-query-context-ids",
|
|
21829
|
+
...timeToFirstChunkFeatures,
|
|
21830
|
+
"trace-query-root-span-fields"
|
|
21577
21831
|
];
|
|
21578
21832
|
return [
|
|
21579
21833
|
"metrics",
|
|
@@ -21588,12 +21842,15 @@ var ObservabilityStoragePostgresVNext = class ObservabilityStoragePostgresVNext
|
|
|
21588
21842
|
"trace-query",
|
|
21589
21843
|
"trace-aggregate",
|
|
21590
21844
|
...spanQueryFeatures,
|
|
21845
|
+
...typeof coreStorage.planThreadRowsQuery === "function" ? ["thread-query-rows"] : [],
|
|
21591
21846
|
"trace-query-root-duration",
|
|
21592
21847
|
"trace-query-discovery",
|
|
21593
21848
|
"thread-query",
|
|
21594
21849
|
"trace-query-tenant-scope",
|
|
21595
21850
|
"feedback",
|
|
21596
|
-
"trace-query-context-ids"
|
|
21851
|
+
"trace-query-context-ids",
|
|
21852
|
+
...timeToFirstChunkFeatures,
|
|
21853
|
+
"trace-query-root-span-fields"
|
|
21597
21854
|
];
|
|
21598
21855
|
}
|
|
21599
21856
|
async #run(op, fn, details) {
|
|
@@ -21655,7 +21912,7 @@ var ObservabilityStoragePostgresVNext = class ObservabilityStoragePostgresVNext
|
|
|
21655
21912
|
return this.#run("GET_TRACE_QUERY_VALUES", () => getTraceQueryValues(this.#readClient, this.#schema, plan, this.#traceQueryTimeoutMs));
|
|
21656
21913
|
}
|
|
21657
21914
|
async queryThreads(plan) {
|
|
21658
|
-
return this.#run("QUERY_THREADS", () => queryThreads(this.#readClient, this.#schema, plan, this.#traceQueryTimeoutMs));
|
|
21915
|
+
return this.#run("QUERY_THREADS", () => plan.result === "threadRows" ? queryThreadRows(this.#readClient, this.#schema, plan, this.#traceQueryTimeoutMs) : queryThreads(this.#readClient, this.#schema, plan, this.#traceQueryTimeoutMs));
|
|
21659
21916
|
}
|
|
21660
21917
|
async listBranches(args) {
|
|
21661
21918
|
return this.#run("LIST_BRANCHES", () => listBranches(this.#readClient, this.#schema, args));
|
|
@@ -24087,7 +24344,7 @@ var SkillsPG = class SkillsPG extends SkillsStorage {
|
|
|
24087
24344
|
}
|
|
24088
24345
|
}
|
|
24089
24346
|
async list(args) {
|
|
24090
|
-
const { page = 0, perPage: perPageInput, orderBy, authorId, visibility, status, entityIds, pinFavoritedFor, favoritedOnly } = args || {};
|
|
24347
|
+
const { page = 0, perPage: perPageInput, orderBy, authorId, visibility, status, entityIds, pinFavoritedFor, favoritedOnly, metadata } = args || {};
|
|
24091
24348
|
const { field, direction } = this.parseOrderBy(orderBy);
|
|
24092
24349
|
if (page < 0) throw new MastraError({
|
|
24093
24350
|
id: createStorageErrorId("PG", "LIST_SKILLS", "INVALID_PAGE"),
|
|
@@ -24132,6 +24389,16 @@ var SkillsPG = class SkillsPG extends SkillsStorage {
|
|
|
24132
24389
|
conditions.push(`s.visibility = $${paramIdx++}`);
|
|
24133
24390
|
queryParams.push(visibility);
|
|
24134
24391
|
}
|
|
24392
|
+
if (metadata && Object.keys(metadata).length > 0) {
|
|
24393
|
+
const versionsTable = getTableName$5({
|
|
24394
|
+
indexName: TABLE_SKILL_VERSIONS,
|
|
24395
|
+
schemaName: getSchemaName$5(this.#schema)
|
|
24396
|
+
});
|
|
24397
|
+
const latestVersionId = `(SELECT lv.id FROM ${versionsTable} lv WHERE lv."skillId" = s.id ORDER BY lv."versionNumber" DESC LIMIT 1)`;
|
|
24398
|
+
const resolvedVersionId = status === "draft" ? latestVersionId : `COALESCE(s."activeVersionId", ${latestVersionId})`;
|
|
24399
|
+
conditions.push(`EXISTS (SELECT 1 FROM ${versionsTable} mv WHERE mv."skillId" = s.id AND mv.id = ${resolvedVersionId} AND mv.metadata @> $${paramIdx++}::jsonb)`);
|
|
24400
|
+
queryParams.push(toPgJson(metadata));
|
|
24401
|
+
}
|
|
24135
24402
|
if (entityIds && entityIds.length > 0) {
|
|
24136
24403
|
const placeholders = entityIds.map(() => `$${paramIdx++}`).join(", ");
|
|
24137
24404
|
conditions.push(`s.id IN (${placeholders})`);
|