@mastra/clickhouse 1.16.1-alpha.1 → 1.16.1-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.
@@ -3,7 +3,7 @@ name: mastra-clickhouse
3
3
  description: Documentation for @mastra/clickhouse. Use when working with @mastra/clickhouse APIs, configuration, or implementation.
4
4
  metadata:
5
5
  package: "@mastra/clickhouse"
6
- version: "1.16.1-alpha.1"
6
+ version: "1.16.1-alpha.2"
7
7
  ---
8
8
 
9
9
  ## When to use
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.16.1-alpha.1",
2
+ "version": "1.16.1-alpha.2",
3
3
  "package": "@mastra/clickhouse",
4
4
  "exports": {},
5
5
  "modules": {}
package/dist/index.cjs CHANGED
@@ -3173,6 +3173,9 @@ CREATE TABLE IF NOT EXISTS ${TABLE_FEEDBACK_EVENTS} (
3173
3173
  feedbackUserId Nullable(String),
3174
3174
  sourceId Nullable(String),
3175
3175
 
3176
+ -- Review workflow
3177
+ reviewStatus LowCardinality(String) DEFAULT 'needs-review',
3178
+
3176
3179
  -- Feedback identity
3177
3180
  feedbackSource LowCardinality(String),
3178
3181
  feedbackType LowCardinality(String),
@@ -3406,6 +3409,7 @@ const ALL_MIGRATIONS = [
3406
3409
  addColumn(TABLE_SCORE_EVENTS, "parentEntityVersionId", "Nullable(String)"),
3407
3410
  addColumn(TABLE_SCORE_EVENTS, "rootEntityVersionId", "Nullable(String)"),
3408
3411
  addColumn(TABLE_FEEDBACK_EVENTS, "entityVersionId", "Nullable(String)"),
3412
+ addColumn(TABLE_FEEDBACK_EVENTS, "reviewStatus", "LowCardinality(String) DEFAULT 'needs-review'"),
3409
3413
  addColumn(TABLE_FEEDBACK_EVENTS, "parentEntityVersionId", "Nullable(String)"),
3410
3414
  addColumn(TABLE_FEEDBACK_EVENTS, "rootEntityVersionId", "Nullable(String)"),
3411
3415
  addBloomIndex(TABLE_METRIC_EVENTS, "idx_traceId", "traceId"),
@@ -3498,6 +3502,31 @@ function parseTtlExpression(expr) {
3498
3502
  };
3499
3503
  }
3500
3504
  //#endregion
3505
+ //#region src/storage/domains/observability/v-next/review-status.ts
3506
+ const FEEDBACK_REVIEW_STATUSES = ["needs-review", "reviewed"];
3507
+ function isFeedbackReviewStatus(value) {
3508
+ return FEEDBACK_REVIEW_STATUSES.some((status) => status === value);
3509
+ }
3510
+ /** Normalize a stored value to a review status, defaulting legacy/unknown values to `needs-review`. */
3511
+ function coerceFeedbackReviewStatus(value) {
3512
+ return isFeedbackReviewStatus(value) ? value : "needs-review";
3513
+ }
3514
+ function parseUpdateFeedbackReviewStatusArgs(args) {
3515
+ const invalid = (text) => new _mastra_core_error.MastraError({
3516
+ id: "OBSERVABILITY_UPDATE_FEEDBACK_REVIEW_STATUS_INVALID_ARGS",
3517
+ domain: _mastra_core_error.ErrorDomain.STORAGE,
3518
+ category: _mastra_core_error.ErrorCategory.USER,
3519
+ text
3520
+ });
3521
+ if (typeof args !== "object" || args === null) throw invalid("args must be an object");
3522
+ if (typeof args.feedbackId !== "string" || args.feedbackId.length === 0) throw invalid("feedbackId is required");
3523
+ if (!isFeedbackReviewStatus(args.reviewStatus)) throw invalid(`reviewStatus must be one of: ${FEEDBACK_REVIEW_STATUSES.join(", ")}`);
3524
+ return {
3525
+ feedbackId: args.feedbackId,
3526
+ reviewStatus: args.reviewStatus
3527
+ };
3528
+ }
3529
+ //#endregion
3501
3530
  //#region src/storage/domains/observability/v-next/helpers.ts
3502
3531
  const CH_SETTINGS = {
3503
3532
  date_time_input_format: "best_effort",
@@ -4004,6 +4033,7 @@ function rowToFeedbackRecord(row) {
4004
4033
  serviceName: nullableString(row.serviceName),
4005
4034
  feedbackUserId,
4006
4035
  sourceId: nullableString(row.sourceId),
4036
+ reviewStatus: coerceFeedbackReviewStatus(row.reviewStatus),
4007
4037
  feedbackSource,
4008
4038
  feedbackType: row.feedbackType,
4009
4039
  value: hasNumber ? Number(row.valueNumber) : nullableString(row.valueString) ?? "",
@@ -4047,6 +4077,7 @@ function feedbackRecordToRow(feedback) {
4047
4077
  serviceName: feedback.serviceName ?? null,
4048
4078
  feedbackUserId,
4049
4079
  sourceId: feedback.sourceId ?? null,
4080
+ reviewStatus: feedback.reviewStatus ?? "needs-review",
4050
4081
  feedbackSource,
4051
4082
  feedbackType: feedback.feedbackType,
4052
4083
  valueString: typeof feedback.value === "string" ? feedback.value : null,
@@ -4344,6 +4375,7 @@ function buildFeedbackFilterConditions(filters, tableAlias) {
4344
4375
  const fbActor = filters.feedbackUserId ?? filters.userId;
4345
4376
  addEq(col("feedbackUserId"), fbActor, "feedbackUserId", "String", out);
4346
4377
  addEq(col("feedbackSource"), filters.feedbackSource, "feedbackSource", "String", out);
4378
+ addEq(col("reviewStatus"), filters.reviewStatus, "reviewStatus", "String", out);
4347
4379
  if (typeof filters.feedbackType === "string") addEq(col("feedbackType"), filters.feedbackType, "feedbackType", "String", out);
4348
4380
  else if (Array.isArray(filters.feedbackType)) addIn(col("feedbackType"), filters.feedbackType, "feedbackTypes", out);
4349
4381
  return out;
@@ -4521,6 +4553,28 @@ async function batchCreateFeedback(client, args) {
4521
4553
  clickhouse_settings: CH_INSERT_SETTINGS
4522
4554
  });
4523
4555
  }
4556
+ async function updateFeedbackReviewStatus(client, args) {
4557
+ const { feedbackId, reviewStatus } = parseUpdateFeedbackReviewStatusArgs(args);
4558
+ const existing = await queryJson$2(client, `SELECT * FROM ${TABLE_FEEDBACK_EVENTS} FINAL WHERE feedbackId = {feedbackId:String} LIMIT 1`, { feedbackId });
4559
+ if (!existing[0]) throw new _mastra_core_error.MastraError({
4560
+ id: "OBSERVABILITY_UPDATE_FEEDBACK_REVIEW_STATUS_NOT_FOUND",
4561
+ domain: _mastra_core_error.ErrorDomain.MASTRA_OBSERVABILITY,
4562
+ category: _mastra_core_error.ErrorCategory.USER,
4563
+ text: "Feedback record not found",
4564
+ details: { feedbackId }
4565
+ });
4566
+ const updated = rowToFeedbackRecord({
4567
+ ...existing[0],
4568
+ reviewStatus
4569
+ });
4570
+ await client.insert({
4571
+ table: TABLE_FEEDBACK_EVENTS,
4572
+ values: [feedbackRecordToRow(updated)],
4573
+ format: "JSONEachRow",
4574
+ clickhouse_settings: CH_INSERT_SETTINGS
4575
+ });
4576
+ return updated;
4577
+ }
4524
4578
  async function listFeedback(client, args, strategy) {
4525
4579
  const parsed = _mastra_core_storage.listFeedbackArgsSchema.parse(args);
4526
4580
  const deltaCursorEnabled = deltaPollingSupported(strategy);
@@ -4552,8 +4606,8 @@ async function listFeedback(client, args, strategy) {
4552
4606
  };
4553
4607
  }
4554
4608
  const currentDeltaCursor = deltaCursorEnabled ? await getDeltaCursor$5(client, whereClause, filter.params) : void 0;
4555
- const countResult = await queryJson$2(client, `SELECT count() AS total FROM ${TABLE_FEEDBACK_EVENTS} AS f ${whereClause}`, filter.params);
4556
- const rows = await queryJson$2(client, `SELECT * FROM ${TABLE_FEEDBACK_EVENTS} AS f ${whereClause} ORDER BY ${orderBy} LIMIT {limit:UInt32} OFFSET {offset:UInt32}`, {
4609
+ const countResult = await queryJson$2(client, `SELECT count() AS total FROM ${TABLE_FEEDBACK_EVENTS} AS f FINAL ${whereClause}`, filter.params);
4610
+ const rows = await queryJson$2(client, `SELECT * FROM ${TABLE_FEEDBACK_EVENTS} AS f FINAL ${whereClause} ORDER BY ${orderBy} LIMIT {limit:UInt32} OFFSET {offset:UInt32}`, {
4557
4611
  ...filter.params,
4558
4612
  limit: pagination.limit,
4559
4613
  offset: pagination.offset
@@ -4579,7 +4633,7 @@ async function queryFeedbackAfterCursor(client, whereClause, params, limit, curs
4579
4633
  f.feedbackId AS feedbackId,
4580
4634
  toString(d.cursorId) AS cursorId
4581
4635
  FROM ${TABLE_FEEDBACK_EVENTS_DELTA} d
4582
- INNER JOIN ${TABLE_FEEDBACK_EVENTS} f
4636
+ INNER JOIN ${TABLE_FEEDBACK_EVENTS} f FINAL
4583
4637
  ON ((f.traceId = d.traceId) OR (f.traceId IS NULL AND d.traceId IS NULL))
4584
4638
  AND f.timestamp = d.timestamp
4585
4639
  AND f.feedbackId = d.feedbackId
@@ -4596,7 +4650,7 @@ async function getDeltaCursor$5(client, whereClause, params) {
4596
4650
  const cursorId = (await queryJson$2(client, `
4597
4651
  SELECT toString(max(d.cursorId)) AS cursorId
4598
4652
  FROM mastra_feedback_events_delta d
4599
- INNER JOIN mastra_feedback_events f
4653
+ INNER JOIN mastra_feedback_events f FINAL
4600
4654
  ON ((f.traceId = d.traceId) OR (f.traceId IS NULL AND d.traceId IS NULL))
4601
4655
  AND f.timestamp = d.timestamp
4602
4656
  AND f.feedbackId = d.feedbackId
@@ -4615,7 +4669,7 @@ async function getFeedbackAggregate(client, args) {
4615
4669
  const aggSql = getAggregationSql$2(args.aggregation);
4616
4670
  const identity = buildFeedbackIdentityFilter(args);
4617
4671
  const combined = mergeFilters$2(identity, buildFeedbackFilterConditions(args.filters));
4618
- const result = await queryJson$2(client, `SELECT ${aggSql} AS value FROM ${TABLE_FEEDBACK_EVENTS} ${toWhereClause$2(combined)}`, combined.params);
4672
+ const result = await queryJson$2(client, `SELECT ${aggSql} AS value FROM ${TABLE_FEEDBACK_EVENTS} FINAL ${toWhereClause$2(combined)}`, combined.params);
4619
4673
  const value = result[0]?.value == null ? null : Number(result[0]?.value);
4620
4674
  if (args.comparePeriod && args.filters?.timestamp) {
4621
4675
  const ts = args.filters.timestamp;
@@ -4649,7 +4703,7 @@ async function getFeedbackAggregate(client, args) {
4649
4703
  endExclusive: ts.endExclusive
4650
4704
  }
4651
4705
  }));
4652
- const prevResult = await queryJson$2(client, `SELECT ${aggSql} AS value FROM ${TABLE_FEEDBACK_EVENTS} ${toWhereClause$2(prevCombined)}`, prevCombined.params);
4706
+ const prevResult = await queryJson$2(client, `SELECT ${aggSql} AS value FROM ${TABLE_FEEDBACK_EVENTS} FINAL ${toWhereClause$2(prevCombined)}`, prevCombined.params);
4653
4707
  const previousValue = prevResult[0]?.value == null ? null : Number(prevResult[0]?.value);
4654
4708
  let changePercent = null;
4655
4709
  if (previousValue !== null && previousValue !== 0 && value !== null) changePercent = (value - previousValue) / Math.abs(previousValue) * 100;
@@ -4667,7 +4721,7 @@ async function getFeedbackBreakdown(client, args) {
4667
4721
  const combined = mergeFilters$2(buildFeedbackIdentityFilter(args), buildFeedbackFilterConditions(args.filters));
4668
4722
  const whereClause = toWhereClause$2(combined);
4669
4723
  const resolved = resolveFeedbackGroupBy(args.groupBy);
4670
- return { groups: (await queryJson$2(client, `SELECT ${resolved.map((e) => e.selectSql).join(", ")}, ${aggSql} AS value FROM ${TABLE_FEEDBACK_EVENTS} ${whereClause} GROUP BY ${resolved.map((e) => e.groupSql).join(", ")} ORDER BY value DESC`, combined.params)).map((row) => ({
4724
+ return { groups: (await queryJson$2(client, `SELECT ${resolved.map((e) => e.selectSql).join(", ")}, ${aggSql} AS value FROM ${TABLE_FEEDBACK_EVENTS} FINAL ${whereClause} GROUP BY ${resolved.map((e) => e.groupSql).join(", ")} ORDER BY value DESC`, combined.params)).map((row) => ({
4671
4725
  dimensions: Object.fromEntries(resolved.map((entry, index) => {
4672
4726
  const v = row[`group_by_${index}`];
4673
4727
  return [entry.key, v == null ? null : String(v)];
@@ -4686,7 +4740,7 @@ async function getFeedbackTimeSeries(client, args) {
4686
4740
  SELECT toStartOfInterval(timestamp, ${intervalSql}) AS bucket,
4687
4741
  ${resolved.map((e) => e.selectSql).join(", ")},
4688
4742
  ${aggSql} AS value
4689
- FROM ${TABLE_FEEDBACK_EVENTS} ${whereClause}
4743
+ FROM ${TABLE_FEEDBACK_EVENTS} FINAL ${whereClause}
4690
4744
  GROUP BY bucket, ${resolved.map((e) => e.groupSql).join(", ")}
4691
4745
  ORDER BY bucket
4692
4746
  `, combined.params);
@@ -4708,7 +4762,7 @@ async function getFeedbackTimeSeries(client, args) {
4708
4762
  const rows = await queryJson$2(client, `
4709
4763
  SELECT toStartOfInterval(timestamp, ${intervalSql}) AS bucket,
4710
4764
  ${aggSql} AS value
4711
- FROM ${TABLE_FEEDBACK_EVENTS} ${whereClause}
4765
+ FROM ${TABLE_FEEDBACK_EVENTS} FINAL ${whereClause}
4712
4766
  GROUP BY bucket
4713
4767
  ORDER BY bucket
4714
4768
  `, combined.params);
@@ -4731,7 +4785,7 @@ async function getFeedbackPercentiles(client, args) {
4731
4785
  const rows = await queryJson$2(client, `
4732
4786
  SELECT toStartOfInterval(timestamp, ${intervalSql}) AS bucket,
4733
4787
  quantile(${p})(valueNumber) AS pvalue
4734
- FROM ${TABLE_FEEDBACK_EVENTS}
4788
+ FROM ${TABLE_FEEDBACK_EVENTS} FINAL
4735
4789
  ${whereClause}
4736
4790
  GROUP BY bucket
4737
4791
  ORDER BY bucket
@@ -7359,6 +7413,19 @@ var ObservabilityStorageClickhouseVNext = class extends _mastra_core_storage.Obs
7359
7413
  }, error);
7360
7414
  }
7361
7415
  }
7416
+ async updateFeedbackReviewStatus(args) {
7417
+ try {
7418
+ return await updateFeedbackReviewStatus(this.#client, args);
7419
+ } catch (error) {
7420
+ if (error instanceof _mastra_core_error.MastraError) throw error;
7421
+ throw new _mastra_core_error.MastraError({
7422
+ id: (0, _mastra_core_storage.createStorageErrorId)("CLICKHOUSE", "UPDATE_FEEDBACK_REVIEW_STATUS", "FAILED"),
7423
+ domain: _mastra_core_error.ErrorDomain.STORAGE,
7424
+ category: _mastra_core_error.ErrorCategory.THIRD_PARTY,
7425
+ details: { feedbackId: args.feedbackId }
7426
+ }, error);
7427
+ }
7428
+ }
7362
7429
  async listFeedback(args) {
7363
7430
  try {
7364
7431
  return await listFeedback(this.#client, args, this.#deltaCursorStrategy);