@mastra/pg 1.31.3-alpha.0 → 1.32.0-alpha.2

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/index.js CHANGED
@@ -6303,7 +6303,11 @@ var DatasetsPG = class DatasetsPG extends DatasetsStorage {
6303
6303
  const queryParams = [];
6304
6304
  let paramIndex = 1;
6305
6305
  if (args.filters) {
6306
- const { organizationId, projectId, candidateKey, candidateId, targetType, targetIds, name } = args.filters;
6306
+ const { organizationId, projectId, candidateKey, candidateId, targetType, targetIds, datasetIds, name } = args.filters;
6307
+ if (datasetIds !== void 0) {
6308
+ conditions.push(`"id" = ANY($${paramIndex++}::text[])`);
6309
+ queryParams.push(datasetIds);
6310
+ }
6307
6311
  if (organizationId !== void 0) {
6308
6312
  conditions.push(`"organizationId" = $${paramIndex++}`);
6309
6313
  queryParams.push(organizationId);
@@ -16006,6 +16010,11 @@ const SPAN_EVENT_COLUMNS = [
16006
16010
  name: "endedAt",
16007
16011
  type: "timestamptz"
16008
16012
  },
16013
+ {
16014
+ name: "timeToFirstChunkMs",
16015
+ type: "double precision",
16016
+ nullable: true
16017
+ },
16009
16018
  {
16010
16019
  name: "tags",
16011
16020
  type: "text[]",
@@ -16740,6 +16749,11 @@ function additiveColumns(schema) {
16740
16749
  column,
16741
16750
  ddl: `ALTER TABLE ${qualifiedTable(schema, TABLE_SPAN_EVENTS)} ADD COLUMN IF NOT EXISTS "${column}" text`
16742
16751
  })),
16752
+ {
16753
+ table: TABLE_SPAN_EVENTS,
16754
+ column: "timeToFirstChunkMs",
16755
+ ddl: `ALTER TABLE ${qualifiedTable(schema, TABLE_SPAN_EVENTS)} ADD COLUMN IF NOT EXISTS "timeToFirstChunkMs" double precision`
16756
+ },
16743
16757
  {
16744
16758
  table: TABLE_FEEDBACK_EVENTS,
16745
16759
  column: "reviewStatus",
@@ -17094,9 +17108,27 @@ function readPreview(preview, payload, jsonEncoded = false) {
17094
17108
  }
17095
17109
  /** Older response builders may shorten previews or turn empty strings into null. */
17096
17110
  function buildSpanQueryResponse(...args) {
17097
- if (canGeneratePreviews) return coreStorage.buildSpanQueryResponse(...args);
17098
- const [plan, selected, payloads, metrics] = args;
17099
- const response = coreStorage.buildSpanQueryResponse(plan, selected, [], metrics);
17111
+ const [plan, selected, payloads, metrics = []] = args;
17112
+ const compatibleSelected = coreStorage.SPAN_QUERY_FIELD_REGISTRY ? selected : selected.map((row) => ({
17113
+ organizationId: row.organizationId,
17114
+ resourceId: row.resourceId,
17115
+ traceId: row.traceId,
17116
+ spanId: row.spanId,
17117
+ parentSpanId: row.parentSpanId,
17118
+ name: row.name,
17119
+ spanType: row.spanType,
17120
+ status: row.status,
17121
+ startedAt: row.startedAt,
17122
+ endedAt: row.endedAt,
17123
+ durationMs: row.durationMs,
17124
+ entityType: row.entityType,
17125
+ entityId: row.entityId,
17126
+ entityName: row.entityName,
17127
+ model: row.model,
17128
+ provider: row.provider
17129
+ }));
17130
+ if (canGeneratePreviews) return coreStorage.buildSpanQueryResponse(plan, compatibleSelected, payloads, metrics);
17131
+ const response = coreStorage.buildSpanQueryResponse(plan, compatibleSelected, [], metrics);
17100
17132
  const byIdentity = new Map(payloads.map((payload) => [coreStorage.spanQueryIdentityKey(payload), payload]));
17101
17133
  for (const span of response.spans) {
17102
17134
  const payload = byIdentity.get(coreStorage.spanQueryIdentityKey(span));
@@ -17443,6 +17475,7 @@ function spanRecordToRow(span) {
17443
17475
  isPending,
17444
17476
  startedAt: toIsoOrDate(span.startedAt),
17445
17477
  endedAt: toIsoOrDate(endedAt),
17478
+ timeToFirstChunkMs: span.timeToFirstChunkMs ?? null,
17446
17479
  tags: normalizeTags(span.tags),
17447
17480
  metadataSearch: buildMetadataSearch(metadata),
17448
17481
  metadataRaw: jsonField(metadata),
@@ -18366,6 +18399,7 @@ async function listLogsDelta(client, table, filters, after, limit) {
18366
18399
  function applyMetricFilters(acc, filters) {
18367
18400
  applyCommonFilters(acc, filters);
18368
18401
  applySingleOrArrayFilter(acc, "traceId", filters?.traceIds);
18402
+ applySingleOrArrayFilter(acc, "experimentId", filters?.experimentIds);
18369
18403
  applySingleOrArrayFilter(acc, "name", filters?.name);
18370
18404
  applySingleOrArrayFilter(acc, "provider", filters?.provider);
18371
18405
  applySingleOrArrayFilter(acc, "model", filters?.model);
@@ -19192,6 +19226,25 @@ const SPAN_FIELDS = {
19192
19226
  userId: "s.\"userId\"",
19193
19227
  organizationId: "s.\"organizationId\""
19194
19228
  };
19229
+ const SPAN_QUERY_FIELDS = {
19230
+ ...SPAN_FIELDS,
19231
+ traceId: "s.\"traceId\"",
19232
+ spanId: "s.\"spanId\"",
19233
+ parentSpanId: "s.\"parentSpanId\"",
19234
+ threadId: "s.\"threadId\"",
19235
+ resourceId: "s.\"resourceId\"",
19236
+ requestId: "s.\"requestId\"",
19237
+ serviceName: "s.\"serviceName\"",
19238
+ experimentId: "s.\"experimentId\"",
19239
+ environment: "s.\"environment\"",
19240
+ executionSource: "s.\"executionSource\"",
19241
+ parentEntityType: "s.\"parentEntityType\"",
19242
+ parentEntityId: "s.\"parentEntityId\"",
19243
+ parentEntityName: "s.\"parentEntityName\"",
19244
+ rootEntityType: "s.\"rootEntityType\"",
19245
+ rootEntityId: "s.\"rootEntityId\"",
19246
+ rootEntityName: "s.\"rootEntityName\""
19247
+ };
19195
19248
  const SCORE_FIELDS = {
19196
19249
  scorerId: "s.\"scorerId\"",
19197
19250
  scorerVersion: "s.\"scorerVersion\"",
@@ -20083,9 +20136,9 @@ async function queryThreads(client, schema, plan, timeoutMs) {
20083
20136
  }) : null }
20084
20137
  });
20085
20138
  }
20086
- /** Compile a span-row filter with exactly the same rules as trace span predicates. */
20139
+ /** Compile a direct span-query filter using its dedicated field mapping. */
20087
20140
  function compileSpanQueryPredicate(predicate, offset) {
20088
- return compileScalarPredicate(predicate, SPAN_FIELDS, offset);
20141
+ return compileScalarPredicate(predicate, SPAN_QUERY_FIELDS, offset);
20089
20142
  }
20090
20143
  //#endregion
20091
20144
  //#region src/storage/domains/observability/v-next/span-query.ts
@@ -20104,11 +20157,23 @@ const fields = [
20104
20157
  "entityId",
20105
20158
  "entityName",
20106
20159
  "entityVersionId",
20160
+ "parentEntityType",
20161
+ "parentEntityId",
20162
+ "parentEntityName",
20107
20163
  "parentEntityVersionId",
20164
+ "rootEntityType",
20165
+ "rootEntityId",
20166
+ "rootEntityName",
20108
20167
  "rootEntityVersionId",
20168
+ "threadId",
20109
20169
  "runId",
20110
20170
  "sessionId",
20111
- "userId"
20171
+ "userId",
20172
+ "requestId",
20173
+ "serviceName",
20174
+ "experimentId",
20175
+ "environment",
20176
+ "executionSource"
20112
20177
  ];
20113
20178
  const identities = identityFields.map((field) => `"${field}"`).join(", ");
20114
20179
  const identityOrder = identityFields.map((field) => `"${field}" COLLATE "C" ASC NULLS LAST`).join(", ");
@@ -20158,6 +20223,8 @@ function compilePostgresSpanQuery(schema, plan) {
20158
20223
  const after = afterCursor(plan, values);
20159
20224
  values.push(plan.limit + 1);
20160
20225
  const table = qualifiedTable(schema, TABLE_SPAN_EVENTS);
20226
+ const legacyModelFields = coreStorage.SPAN_QUERY_FIELD_REGISTRY ? "" : `CASE WHEN jsonb_typeof(attributes -> 'model') = 'string' THEN attributes ->> 'model' END AS model,
20227
+ CASE WHEN jsonb_typeof(attributes -> 'provider') = 'string' THEN attributes ->> 'provider' END AS provider,`;
20161
20228
  return {
20162
20229
  text: `WITH candidate_ids AS MATERIALIZED (
20163
20230
  SELECT DISTINCT ${identities} FROM ${table}
@@ -20166,8 +20233,7 @@ function compilePostgresSpanQuery(schema, plan) {
20166
20233
  ), current_spans AS MATERIALIZED (
20167
20234
  SELECT DISTINCT ON (${identities})
20168
20235
  ${fields.map((field) => `"${field}"`).join(", ")}, "startedAt", "endedAt", "cursorId"::text AS version,
20169
- CASE WHEN jsonb_typeof(attributes -> 'model') = 'string' THEN attributes ->> 'model' END AS model,
20170
- CASE WHEN jsonb_typeof(attributes -> 'provider') = 'string' THEN attributes ->> 'provider' END AS provider,
20236
+ ${legacyModelFields}
20171
20237
  (EXTRACT(EPOCH FROM ("endedAt" - "startedAt")) * 1000)::float8 AS "durationMs",
20172
20238
  CASE WHEN error IS NULL THEN 'success' ELSE 'error' END AS status,
20173
20239
  error IS NOT NULL AS "hasError"
@@ -20182,15 +20248,7 @@ function compilePostgresSpanQuery(schema, plan) {
20182
20248
  SELECT *, CASE WHEN "hasError" THEN 'error' ELSE NULL END AS error FROM current_spans
20183
20249
  )
20184
20250
  SELECT ${[
20185
- ...identityFields,
20186
- "parentSpanId",
20187
- "name",
20188
- "spanType",
20189
- "entityType",
20190
- "entityId",
20191
- "entityName",
20192
- "model",
20193
- "provider",
20251
+ ...fields,
20194
20252
  "startedAt",
20195
20253
  "endedAt",
20196
20254
  "durationMs",
@@ -20237,7 +20295,7 @@ async function querySpans(client, schema, plan, timeoutMs) {
20237
20295
  endedAt: endedAt.toISOString()
20238
20296
  }));
20239
20297
  const page = rows.slice(0, plan.limit);
20240
- if (!page.length) return coreStorage.buildSpanQueryResponse(plan, selected, [], []);
20298
+ if (!page.length) return buildSpanQueryResponse(plan, [], []);
20241
20299
  const remaining = async () => {
20242
20300
  const ms = Math.floor(deadline - performance.now());
20243
20301
  if (ms <= 0) throw new coreStorage.TraceQueryExecutionError();
@@ -20250,20 +20308,32 @@ async function querySpans(client, schema, plan, timeoutMs) {
20250
20308
  payloadValues.push(row.version);
20251
20309
  return `(${key} AND "cursorId" = $${payloadValues.length}::bigint)`;
20252
20310
  }).join(" OR ");
20253
- const payloads = (await tx.any(`SELECT ${identities},
20311
+ const payloadRows = await tx.any(`SELECT ${identities},
20312
+ CASE WHEN jsonb_typeof(attributes -> 'model') = 'string' THEN attributes ->> 'model' END AS model,
20313
+ CASE WHEN jsonb_typeof(attributes -> 'provider') = 'string' THEN attributes ->> 'provider' END AS provider,
20254
20314
  ${PREVIEW_PAYLOADS$1.map(([preview, payload]) => `"${preview}", CASE WHEN ${missingPreviewSql(`"${preview}"`)} THEN "${payload}" END AS "${payload}"`).join(",\n ")}
20255
- FROM ${qualifiedTable(schema, TABLE_SPAN_EVENTS)} WHERE ${payloadWhere}`, payloadValues)).map(toSpanQueryPayload);
20256
- await remaining();
20257
- const metricValues = [];
20258
- const metricWhere = selectedKeys(page, metricValues);
20259
- const metrics = await tx.any(`SELECT ${identities}, name, "estimatedCost", "costUnit",
20260
- "costMetadata" ->> 'allocation' AS allocation, COALESCE("costMetadata" ? 'error', false) AS "costError"
20261
- FROM (SELECT DISTINCT ON (${identities}, "metricId") ${identities}, name, "estimatedCost", "costUnit", "costMetadata" FROM ${qualifiedTable(schema, TABLE_METRIC_EVENTS)}
20262
- WHERE (${metricWhere}) AND name LIKE 'mastra_model_%'
20263
- ORDER BY ${identities}, "metricId", "cursorId" DESC) m
20264
- LIMIT ${coreStorage.SPAN_QUERY_MAX_COST_METRICS + 1}`, metricValues);
20265
- if (metrics.length > coreStorage.SPAN_QUERY_MAX_COST_METRICS) throw new coreStorage.TraceQueryResourceLimitError();
20266
- return buildSpanQueryResponse(plan, selected, payloads, metrics);
20315
+ FROM ${qualifiedTable(schema, TABLE_SPAN_EVENTS)} WHERE ${payloadWhere}`, payloadValues);
20316
+ const payloads = payloadRows.map(toSpanQueryPayload);
20317
+ const metadata = new Map(payloadRows.map((row) => [coreStorage.spanQueryIdentityKey(row), row]));
20318
+ const hydrated = selected.map((row) => ({
20319
+ ...row,
20320
+ model: metadata.get(coreStorage.spanQueryIdentityKey(row))?.model ?? null,
20321
+ provider: metadata.get(coreStorage.spanQueryIdentityKey(row))?.provider ?? null
20322
+ }));
20323
+ let metrics = [];
20324
+ if (!coreStorage.SPAN_QUERY_FIELD_REGISTRY) {
20325
+ await remaining();
20326
+ const metricValues = [];
20327
+ const metricWhere = selectedKeys(page, metricValues);
20328
+ metrics = await tx.any(`SELECT ${identities}, name, "estimatedCost", "costUnit",
20329
+ "costMetadata" ->> 'allocation' AS allocation, COALESCE("costMetadata" ? 'error', false) AS "costError"
20330
+ FROM (SELECT DISTINCT ON (${identities}, "metricId") ${identities}, name, "estimatedCost", "costUnit", "costMetadata" FROM ${qualifiedTable(schema, TABLE_METRIC_EVENTS)}
20331
+ WHERE (${metricWhere}) AND name LIKE 'mastra_model_%'
20332
+ ORDER BY ${identities}, "metricId", "cursorId" DESC) m
20333
+ LIMIT ${coreStorage.SPAN_QUERY_MAX_COST_METRICS + 1}`, metricValues);
20334
+ if (metrics.length > coreStorage.SPAN_QUERY_MAX_COST_METRICS) throw new coreStorage.TraceQueryResourceLimitError();
20335
+ }
20336
+ return buildSpanQueryResponse(plan, hydrated, payloads, metrics);
20267
20337
  }, { repeatableRead: true });
20268
20338
  }
20269
20339
  //#endregion
@@ -21307,7 +21377,7 @@ async function dangerouslyClearTracing(client, schema) {
21307
21377
  * application database — observability writes will degrade app performance.
21308
21378
  * Use it through `MastraCompositeStore` with a dedicated Postgres connection.
21309
21379
  */
21310
- const spanQueryFeatures = typeof coreStorage.planSpanQuery === "function" ? ["span-query"] : [];
21380
+ const spanQueryFeatures = typeof coreStorage.planSpanQuery === "function" ? ["span-query", "span-query-context-fields"] : [];
21311
21381
  function wrapError(op, error, details) {
21312
21382
  if (error instanceof MastraError || error instanceof coreStorage.TraceQueryCursorError || error instanceof coreStorage.TraceQueryExecutionError || error instanceof coreStorage.TraceQueryResourceLimitError) throw error;
21313
21383
  throw new MastraError({