@mastra/pg 1.24.0-alpha.2 → 1.24.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.
@@ -3,7 +3,7 @@ name: mastra-pg
3
3
  description: Documentation for @mastra/pg. Use when working with @mastra/pg APIs, configuration, or implementation.
4
4
  metadata:
5
5
  package: "@mastra/pg"
6
- version: "1.24.0-alpha.2"
6
+ version: "1.24.0-alpha.3"
7
7
  ---
8
8
 
9
9
  ## When to use
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.24.0-alpha.2",
2
+ "version": "1.24.0-alpha.3",
3
3
  "package": "@mastra/pg",
4
4
  "exports": {},
5
5
  "modules": {}
package/dist/index.cjs CHANGED
@@ -16102,6 +16102,8 @@ ${buildSelectColumns(FEEDBACK_EVENT_COLUMNS)}`;
16102
16102
  * aggregate, breakdown, time series, and percentiles. OLAP aggregates run
16103
16103
  * over `valueNumber` only; string-valued feedback is excluded.
16104
16104
  */
16105
+ const FEEDBACK_CONFLICT_KEYS = /* @__PURE__ */ new Set(["feedbackId", "timestamp"]);
16106
+ const FEEDBACK_UPSERT_CLAUSE = `ON CONFLICT ("feedbackId", "timestamp") DO UPDATE SET ${FEEDBACK_EVENT_COLUMNS.map((column) => column.name).filter((column) => !FEEDBACK_CONFLICT_KEYS.has(column)).map((column) => `"${column}" = EXCLUDED."${column}"`).join(", ")}`;
16105
16107
  function applyFeedbackFilters(acc, filters) {
16106
16108
  applyCommonFilters(acc, filters);
16107
16109
  applySingleOrArrayFilter(acc, "feedbackType", filters?.feedbackType);
@@ -16132,12 +16134,12 @@ function pushFeedbackIdentity(acc, feedbackType, feedbackSource) {
16132
16134
  acc.conditions.push(`"valueNumber" IS NOT NULL`);
16133
16135
  }
16134
16136
  async function createFeedback(client, schema, args) {
16135
- const insert = buildInsert(schema, TABLE_FEEDBACK_EVENTS, [feedbackRecordToRow(args.feedback)]);
16137
+ const insert = buildInsert(schema, TABLE_FEEDBACK_EVENTS, [feedbackRecordToRow(args.feedback)], FEEDBACK_UPSERT_CLAUSE);
16136
16138
  if (insert) await client.query(insert.text, insert.values);
16137
16139
  }
16138
16140
  async function batchCreateFeedback(client, schema, args) {
16139
16141
  if (args.feedbacks.length === 0) return;
16140
- const insert = buildInsert(schema, TABLE_FEEDBACK_EVENTS, args.feedbacks.map(feedbackRecordToRow));
16142
+ const insert = buildInsert(schema, TABLE_FEEDBACK_EVENTS, [...new Map(args.feedbacks.map((feedback) => [feedback.feedbackId, feedback])).values()].map(feedbackRecordToRow), FEEDBACK_UPSERT_CLAUSE);
16141
16143
  if (insert) await client.query(insert.text, insert.values);
16142
16144
  }
16143
16145
  async function updateFeedbackReviewStatus(client, schema, args) {
@@ -17158,6 +17160,17 @@ const SCORE_FIELDS = {
17158
17160
  parentEntityVersionId: "s.\"parentEntityVersionId\"",
17159
17161
  rootEntityVersionId: "s.\"rootEntityVersionId\""
17160
17162
  };
17163
+ const FEEDBACK_FIELDS = {
17164
+ feedbackType: "s.\"feedbackType\"",
17165
+ feedbackSource: "s.\"feedbackSource\"",
17166
+ feedbackUserId: "s.\"feedbackUserId\"",
17167
+ sourceId: "s.\"sourceId\"",
17168
+ entityVersionId: "s.\"entityVersionId\"",
17169
+ parentEntityVersionId: "s.\"parentEntityVersionId\"",
17170
+ rootEntityVersionId: "s.\"rootEntityVersionId\"",
17171
+ timestamp: "s.\"timestamp\"",
17172
+ comment: "s.\"comment\""
17173
+ };
17161
17174
  const TRACE_SELECT = `
17162
17175
  r."traceId" AS "traceId",
17163
17176
  r."spanId" AS "rootSpanId",
@@ -17247,6 +17260,35 @@ function compileScalarPredicate(predicate, registry, parameterOffset, allowMetad
17247
17260
  values: [...fieldValues, predicate.value]
17248
17261
  };
17249
17262
  }
17263
+ function compileFeedbackScalarPredicate(predicate, parameterOffset) {
17264
+ if (predicate.type === "boolean") {
17265
+ const values = [];
17266
+ return {
17267
+ sql: predicate.args.map((arg) => {
17268
+ const compiled = compileFeedbackScalarPredicate(arg, parameterOffset + values.length);
17269
+ values.push(...compiled.values);
17270
+ return `(${compiled.sql})`;
17271
+ }).join(predicate.operator === "and" ? " AND " : " OR "),
17272
+ values
17273
+ };
17274
+ }
17275
+ if (predicate.type === "not") {
17276
+ const compiled = compileFeedbackScalarPredicate(predicate.arg, parameterOffset);
17277
+ return {
17278
+ sql: `NOT (${compiled.sql})`,
17279
+ values: compiled.values
17280
+ };
17281
+ }
17282
+ if (predicate.field !== "value") return compileScalarPredicate(predicate, FEEDBACK_FIELDS, parameterOffset);
17283
+ if (predicate.type === "presence") {
17284
+ const present = `(s."valueString" IS NOT NULL OR s."valueNumber" IS NOT NULL)`;
17285
+ return {
17286
+ sql: predicate.operator === "exists" ? present : `NOT ${present}`,
17287
+ values: []
17288
+ };
17289
+ }
17290
+ return compileScalarPredicate(predicate, { value: typeof (predicate.type === "membership" ? predicate.values[0] : predicate.value) === "number" ? "s.\"valueNumber\"" : "s.\"valueString\"" }, parameterOffset);
17291
+ }
17250
17292
  function latestRootPredicate$1(spanTable) {
17251
17293
  return `NOT EXISTS (
17252
17294
  SELECT 1 FROM ${spanTable} newer
@@ -17270,6 +17312,13 @@ function latestScorePredicate(scoreTable) {
17270
17312
  AND newer."cursorId" > s."cursorId"
17271
17313
  )`;
17272
17314
  }
17315
+ function latestFeedbackPredicate(feedbackTable) {
17316
+ return `NOT EXISTS (
17317
+ SELECT 1 FROM ${feedbackTable} newer
17318
+ WHERE newer."feedbackId" = s."feedbackId"
17319
+ AND newer."cursorId" > s."cursorId"
17320
+ )`;
17321
+ }
17273
17322
  function collectRelationCollections(predicate, collections = /* @__PURE__ */ new Set()) {
17274
17323
  if (!predicate) return collections;
17275
17324
  if (predicate.type === "relation") collections.add(predicate.collection);
@@ -17279,11 +17328,11 @@ function collectRelationCollections(predicate, collections = /* @__PURE__ */ new
17279
17328
  }
17280
17329
  function compilePredicate(predicate, parameterOffset) {
17281
17330
  if (predicate.type === "relation") {
17282
- const registry = predicate.collection === "spans" ? SPAN_FIELDS : SCORE_FIELDS;
17283
- const compiled = compileScalarPredicate(predicate.predicate, registry, parameterOffset);
17331
+ const compiled = predicate.collection === "feedback" ? compileFeedbackScalarPredicate(predicate.predicate, parameterOffset) : compileScalarPredicate(predicate.predicate, predicate.collection === "spans" ? SPAN_FIELDS : SCORE_FIELDS, parameterOffset);
17284
17332
  const existence = `EXISTS (
17285
- SELECT 1 FROM ${predicate.collection === "spans" ? "current_spans" : "current_scores"} s
17286
- WHERE s."traceId" = r."traceId"
17333
+ SELECT 1 FROM ${predicate.collection === "spans" ? "current_spans" : predicate.collection === "scores" ? "current_scores" : "current_feedback"} s
17334
+ WHERE s."traceId" IS NOT NULL
17335
+ AND s."traceId" = r."traceId"
17287
17336
  AND (${compiled.sql})
17288
17337
  )`;
17289
17338
  return {
@@ -17314,6 +17363,7 @@ function compilePredicate(predicate, parameterOffset) {
17314
17363
  function compilePostgresTraceQuery(schema, plan) {
17315
17364
  const spanTable = qualifiedTable(schema, TABLE_SPAN_EVENTS);
17316
17365
  const scoreTable = qualifiedTable(schema, TABLE_SCORE_EVENTS);
17366
+ const feedbackTable = qualifiedTable(schema, TABLE_FEEDBACK_EVENTS);
17317
17367
  const values = [plan.timeRange.from, plan.timeRange.to];
17318
17368
  const relationCollections = collectRelationCollections(plan.where);
17319
17369
  const ctes = [`root_scope AS MATERIALIZED (
@@ -17370,6 +17420,25 @@ function compilePostgresTraceQuery(schema, plan) {
17370
17420
  WHERE s."traceId" IS NOT NULL
17371
17421
  AND s."traceId" IN (SELECT "traceId" FROM root_scope)
17372
17422
  AND ${latestScorePredicate(scoreTable)}
17423
+ )`);
17424
+ if (relationCollections.has("feedback")) ctes.push(`current_feedback AS MATERIALIZED (
17425
+ SELECT
17426
+ s."traceId",
17427
+ s."feedbackType",
17428
+ s."feedbackSource",
17429
+ s."feedbackUserId",
17430
+ s."sourceId",
17431
+ s."valueString",
17432
+ s."valueNumber",
17433
+ s."comment",
17434
+ s."timestamp",
17435
+ s."entityVersionId",
17436
+ s."parentEntityVersionId",
17437
+ s."rootEntityVersionId"
17438
+ FROM ${feedbackTable} s
17439
+ WHERE s."traceId" IS NOT NULL
17440
+ AND s."traceId" IN (SELECT "traceId" FROM root_scope)
17441
+ AND ${latestFeedbackPredicate(feedbackTable)}
17373
17442
  )`);
17374
17443
  let predicateSql = "TRUE";
17375
17444
  if (plan.where) {