@mastra/pg 1.24.0-alpha.1 → 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.
package/dist/index.js CHANGED
@@ -16078,6 +16078,8 @@ ${buildSelectColumns(FEEDBACK_EVENT_COLUMNS)}`;
16078
16078
  * aggregate, breakdown, time series, and percentiles. OLAP aggregates run
16079
16079
  * over `valueNumber` only; string-valued feedback is excluded.
16080
16080
  */
16081
+ const FEEDBACK_CONFLICT_KEYS = /* @__PURE__ */ new Set(["feedbackId", "timestamp"]);
16082
+ 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(", ")}`;
16081
16083
  function applyFeedbackFilters(acc, filters) {
16082
16084
  applyCommonFilters(acc, filters);
16083
16085
  applySingleOrArrayFilter(acc, "feedbackType", filters?.feedbackType);
@@ -16108,12 +16110,12 @@ function pushFeedbackIdentity(acc, feedbackType, feedbackSource) {
16108
16110
  acc.conditions.push(`"valueNumber" IS NOT NULL`);
16109
16111
  }
16110
16112
  async function createFeedback(client, schema, args) {
16111
- const insert = buildInsert(schema, TABLE_FEEDBACK_EVENTS, [feedbackRecordToRow(args.feedback)]);
16113
+ const insert = buildInsert(schema, TABLE_FEEDBACK_EVENTS, [feedbackRecordToRow(args.feedback)], FEEDBACK_UPSERT_CLAUSE);
16112
16114
  if (insert) await client.query(insert.text, insert.values);
16113
16115
  }
16114
16116
  async function batchCreateFeedback(client, schema, args) {
16115
16117
  if (args.feedbacks.length === 0) return;
16116
- const insert = buildInsert(schema, TABLE_FEEDBACK_EVENTS, args.feedbacks.map(feedbackRecordToRow));
16118
+ const insert = buildInsert(schema, TABLE_FEEDBACK_EVENTS, [...new Map(args.feedbacks.map((feedback) => [feedback.feedbackId, feedback])).values()].map(feedbackRecordToRow), FEEDBACK_UPSERT_CLAUSE);
16117
16119
  if (insert) await client.query(insert.text, insert.values);
16118
16120
  }
16119
16121
  async function updateFeedbackReviewStatus(client, schema, args) {
@@ -16131,6 +16133,26 @@ async function updateFeedbackReviewStatus(client, schema, args) {
16131
16133
  });
16132
16134
  return rowToFeedbackRecord(row);
16133
16135
  }
16136
+ /**
16137
+ * Delete feedback events by feedbackId. Optional `organizationId` and
16138
+ * `resourceId` values are ANDed into the predicate to restrict deletion to
16139
+ * records with matching scope fields.
16140
+ */
16141
+ async function deleteFeedback(client, schema, args) {
16142
+ if (args.feedbackIds.length === 0) return;
16143
+ const table = qualifiedTable(schema, TABLE_FEEDBACK_EVENTS);
16144
+ const values = [...args.feedbackIds];
16145
+ const conditions = [`"feedbackId" IN (${args.feedbackIds.map((_, i) => `$${i + 1}`).join(", ")})`];
16146
+ if (args.organizationId !== void 0) {
16147
+ values.push(args.organizationId);
16148
+ conditions.push(`"organizationId" = $${values.length}`);
16149
+ }
16150
+ if (args.resourceId !== void 0) {
16151
+ values.push(args.resourceId);
16152
+ conditions.push(`"resourceId" = $${values.length}`);
16153
+ }
16154
+ await client.query(`DELETE FROM ${table} WHERE ${conditions.join(" AND ")}`, values);
16155
+ }
16134
16156
  async function listFeedback(client, schema, args) {
16135
16157
  const { mode, filters, pagination, orderBy, after, limit } = listFeedbackArgsSchema.parse(args);
16136
16158
  const table = qualifiedTable(schema, TABLE_FEEDBACK_EVENTS);
@@ -16891,6 +16913,26 @@ async function batchCreateScores(client, schema, args) {
16891
16913
  const insert = buildInsert(schema, TABLE_SCORE_EVENTS, args.scores.map(scoreRecordToRow));
16892
16914
  if (insert) await client.query(insert.text, insert.values);
16893
16915
  }
16916
+ /**
16917
+ * Delete score events by scoreId. Optional `organizationId` and `resourceId`
16918
+ * values are ANDed into the predicate to restrict deletion to records with
16919
+ * matching scope fields.
16920
+ */
16921
+ async function deleteScores(client, schema, args) {
16922
+ if (args.scoreIds.length === 0) return;
16923
+ const table = qualifiedTable(schema, TABLE_SCORE_EVENTS);
16924
+ const values = [...args.scoreIds];
16925
+ const conditions = [`"scoreId" IN (${args.scoreIds.map((_, i) => `$${i + 1}`).join(", ")})`];
16926
+ if (args.organizationId !== void 0) {
16927
+ values.push(args.organizationId);
16928
+ conditions.push(`"organizationId" = $${values.length}`);
16929
+ }
16930
+ if (args.resourceId !== void 0) {
16931
+ values.push(args.resourceId);
16932
+ conditions.push(`"resourceId" = $${values.length}`);
16933
+ }
16934
+ await client.query(`DELETE FROM ${table} WHERE ${conditions.join(" AND ")}`, values);
16935
+ }
16894
16936
  async function listScores(client, schema, args) {
16895
16937
  const { mode, filters, pagination, orderBy, after, limit } = listScoresArgsSchema.parse(args);
16896
16938
  const table = qualifiedTable(schema, TABLE_SCORE_EVENTS);
@@ -17094,6 +17136,17 @@ const SCORE_FIELDS = {
17094
17136
  parentEntityVersionId: "s.\"parentEntityVersionId\"",
17095
17137
  rootEntityVersionId: "s.\"rootEntityVersionId\""
17096
17138
  };
17139
+ const FEEDBACK_FIELDS = {
17140
+ feedbackType: "s.\"feedbackType\"",
17141
+ feedbackSource: "s.\"feedbackSource\"",
17142
+ feedbackUserId: "s.\"feedbackUserId\"",
17143
+ sourceId: "s.\"sourceId\"",
17144
+ entityVersionId: "s.\"entityVersionId\"",
17145
+ parentEntityVersionId: "s.\"parentEntityVersionId\"",
17146
+ rootEntityVersionId: "s.\"rootEntityVersionId\"",
17147
+ timestamp: "s.\"timestamp\"",
17148
+ comment: "s.\"comment\""
17149
+ };
17097
17150
  const TRACE_SELECT = `
17098
17151
  r."traceId" AS "traceId",
17099
17152
  r."spanId" AS "rootSpanId",
@@ -17183,6 +17236,35 @@ function compileScalarPredicate(predicate, registry, parameterOffset, allowMetad
17183
17236
  values: [...fieldValues, predicate.value]
17184
17237
  };
17185
17238
  }
17239
+ function compileFeedbackScalarPredicate(predicate, parameterOffset) {
17240
+ if (predicate.type === "boolean") {
17241
+ const values = [];
17242
+ return {
17243
+ sql: predicate.args.map((arg) => {
17244
+ const compiled = compileFeedbackScalarPredicate(arg, parameterOffset + values.length);
17245
+ values.push(...compiled.values);
17246
+ return `(${compiled.sql})`;
17247
+ }).join(predicate.operator === "and" ? " AND " : " OR "),
17248
+ values
17249
+ };
17250
+ }
17251
+ if (predicate.type === "not") {
17252
+ const compiled = compileFeedbackScalarPredicate(predicate.arg, parameterOffset);
17253
+ return {
17254
+ sql: `NOT (${compiled.sql})`,
17255
+ values: compiled.values
17256
+ };
17257
+ }
17258
+ if (predicate.field !== "value") return compileScalarPredicate(predicate, FEEDBACK_FIELDS, parameterOffset);
17259
+ if (predicate.type === "presence") {
17260
+ const present = `(s."valueString" IS NOT NULL OR s."valueNumber" IS NOT NULL)`;
17261
+ return {
17262
+ sql: predicate.operator === "exists" ? present : `NOT ${present}`,
17263
+ values: []
17264
+ };
17265
+ }
17266
+ return compileScalarPredicate(predicate, { value: typeof (predicate.type === "membership" ? predicate.values[0] : predicate.value) === "number" ? "s.\"valueNumber\"" : "s.\"valueString\"" }, parameterOffset);
17267
+ }
17186
17268
  function latestRootPredicate$1(spanTable) {
17187
17269
  return `NOT EXISTS (
17188
17270
  SELECT 1 FROM ${spanTable} newer
@@ -17206,6 +17288,13 @@ function latestScorePredicate(scoreTable) {
17206
17288
  AND newer."cursorId" > s."cursorId"
17207
17289
  )`;
17208
17290
  }
17291
+ function latestFeedbackPredicate(feedbackTable) {
17292
+ return `NOT EXISTS (
17293
+ SELECT 1 FROM ${feedbackTable} newer
17294
+ WHERE newer."feedbackId" = s."feedbackId"
17295
+ AND newer."cursorId" > s."cursorId"
17296
+ )`;
17297
+ }
17209
17298
  function collectRelationCollections(predicate, collections = /* @__PURE__ */ new Set()) {
17210
17299
  if (!predicate) return collections;
17211
17300
  if (predicate.type === "relation") collections.add(predicate.collection);
@@ -17215,11 +17304,11 @@ function collectRelationCollections(predicate, collections = /* @__PURE__ */ new
17215
17304
  }
17216
17305
  function compilePredicate(predicate, parameterOffset) {
17217
17306
  if (predicate.type === "relation") {
17218
- const registry = predicate.collection === "spans" ? SPAN_FIELDS : SCORE_FIELDS;
17219
- const compiled = compileScalarPredicate(predicate.predicate, registry, parameterOffset);
17307
+ const compiled = predicate.collection === "feedback" ? compileFeedbackScalarPredicate(predicate.predicate, parameterOffset) : compileScalarPredicate(predicate.predicate, predicate.collection === "spans" ? SPAN_FIELDS : SCORE_FIELDS, parameterOffset);
17220
17308
  const existence = `EXISTS (
17221
- SELECT 1 FROM ${predicate.collection === "spans" ? "current_spans" : "current_scores"} s
17222
- WHERE s."traceId" = r."traceId"
17309
+ SELECT 1 FROM ${predicate.collection === "spans" ? "current_spans" : predicate.collection === "scores" ? "current_scores" : "current_feedback"} s
17310
+ WHERE s."traceId" IS NOT NULL
17311
+ AND s."traceId" = r."traceId"
17223
17312
  AND (${compiled.sql})
17224
17313
  )`;
17225
17314
  return {
@@ -17250,6 +17339,7 @@ function compilePredicate(predicate, parameterOffset) {
17250
17339
  function compilePostgresTraceQuery(schema, plan) {
17251
17340
  const spanTable = qualifiedTable(schema, TABLE_SPAN_EVENTS);
17252
17341
  const scoreTable = qualifiedTable(schema, TABLE_SCORE_EVENTS);
17342
+ const feedbackTable = qualifiedTable(schema, TABLE_FEEDBACK_EVENTS);
17253
17343
  const values = [plan.timeRange.from, plan.timeRange.to];
17254
17344
  const relationCollections = collectRelationCollections(plan.where);
17255
17345
  const ctes = [`root_scope AS MATERIALIZED (
@@ -17306,6 +17396,25 @@ function compilePostgresTraceQuery(schema, plan) {
17306
17396
  WHERE s."traceId" IS NOT NULL
17307
17397
  AND s."traceId" IN (SELECT "traceId" FROM root_scope)
17308
17398
  AND ${latestScorePredicate(scoreTable)}
17399
+ )`);
17400
+ if (relationCollections.has("feedback")) ctes.push(`current_feedback AS MATERIALIZED (
17401
+ SELECT
17402
+ s."traceId",
17403
+ s."feedbackType",
17404
+ s."feedbackSource",
17405
+ s."feedbackUserId",
17406
+ s."sourceId",
17407
+ s."valueString",
17408
+ s."valueNumber",
17409
+ s."comment",
17410
+ s."timestamp",
17411
+ s."entityVersionId",
17412
+ s."parentEntityVersionId",
17413
+ s."rootEntityVersionId"
17414
+ FROM ${feedbackTable} s
17415
+ WHERE s."traceId" IS NOT NULL
17416
+ AND s."traceId" IN (SELECT "traceId" FROM root_scope)
17417
+ AND ${latestFeedbackPredicate(feedbackTable)}
17309
17418
  )`);
17310
17419
  let predicateSql = "TRUE";
17311
17420
  if (plan.where) {
@@ -18380,6 +18489,12 @@ var ObservabilityStoragePostgresVNext = class ObservabilityStoragePostgresVNext
18380
18489
  async batchCreateFeedback(args) {
18381
18490
  await this.#run("BATCH_CREATE_FEEDBACK", () => batchCreateFeedback(this.#client, this.#schema, args), { count: args.feedbacks.length });
18382
18491
  }
18492
+ async deleteScores(args) {
18493
+ await this.#run("DELETE_SCORES", () => deleteScores(this.#client, this.#schema, args), { count: args.scoreIds.length });
18494
+ }
18495
+ async deleteFeedback(args) {
18496
+ await this.#run("DELETE_FEEDBACK", () => deleteFeedback(this.#client, this.#schema, args), { count: args.feedbackIds.length });
18497
+ }
18383
18498
  async listLogs(args) {
18384
18499
  return this.#run("LIST_LOGS", () => listLogs(this.#readClient, this.#schema, args));
18385
18500
  }