@mastra/duckdb 1.7.0 → 1.8.0-alpha.1

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.
@@ -74,6 +74,8 @@ CREATE TABLE IF NOT EXISTS span_events (
74
74
  entityId VARCHAR,
75
75
  entityName VARCHAR,
76
76
  entityVersionId VARCHAR,
77
+ parentEntityVersionId VARCHAR,
78
+ rootEntityVersionId VARCHAR,
77
79
 
78
80
  -- Context
79
81
  userId VARCHAR,
@@ -339,6 +341,8 @@ const ALL_MIGRATIONS = [
339
341
  `CREATE SEQUENCE IF NOT EXISTS feedback_events_cursor_id_seq START 1`,
340
342
  `ALTER TABLE span_events ADD COLUMN IF NOT EXISTS cursorId BIGINT`,
341
343
  `ALTER TABLE span_events ADD COLUMN IF NOT EXISTS entityVersionId VARCHAR`,
344
+ `ALTER TABLE span_events ADD COLUMN IF NOT EXISTS parentEntityVersionId VARCHAR`,
345
+ `ALTER TABLE span_events ADD COLUMN IF NOT EXISTS rootEntityVersionId VARCHAR`,
342
346
  `ALTER TABLE metric_events ADD COLUMN IF NOT EXISTS cursorId BIGINT`,
343
347
  `ALTER TABLE metric_events ADD COLUMN IF NOT EXISTS entityVersionId VARCHAR`,
344
348
  `ALTER TABLE metric_events ADD COLUMN IF NOT EXISTS parentEntityVersionId VARCHAR`,
@@ -1038,6 +1042,25 @@ async function batchCreateFeedback(db, args) {
1038
1042
  VALUES ${tuples.join(",\n ")}
1039
1043
  ON CONFLICT DO NOTHING`);
1040
1044
  }
1045
+ /**
1046
+ * Delete feedback events by feedbackId. Optional `organizationId` and
1047
+ * `resourceId` values are ANDed into the predicate to restrict deletion to
1048
+ * records with matching scope fields.
1049
+ */
1050
+ async function deleteFeedback(db, args) {
1051
+ if (args.feedbackIds.length === 0) return;
1052
+ const conditions = [`feedbackId IN (${args.feedbackIds.map(() => "?").join(", ")})`];
1053
+ const params = [...args.feedbackIds];
1054
+ if (args.organizationId !== void 0) {
1055
+ conditions.push("organizationId = ?");
1056
+ params.push(args.organizationId);
1057
+ }
1058
+ if (args.resourceId !== void 0) {
1059
+ conditions.push("resourceId = ?");
1060
+ params.push(args.resourceId);
1061
+ }
1062
+ await db.execute(`DELETE FROM feedback_events WHERE ${conditions.join(" AND ")}`, params);
1063
+ }
1041
1064
  /** Update the review workflow status of a single feedback event. */
1042
1065
  async function updateFeedbackReviewStatus(db, args) {
1043
1066
  const { feedbackId, reviewStatus } = parseUpdateFeedbackReviewStatusArgs(args);
@@ -2395,6 +2418,25 @@ async function batchCreateScores(db, args) {
2395
2418
  VALUES ${tuples.join(",\n ")}
2396
2419
  ${SCORE_UPSERT_CLAUSE}`);
2397
2420
  }
2421
+ /**
2422
+ * Delete score events by scoreId. Optional `organizationId` and `resourceId`
2423
+ * values are ANDed into the predicate to restrict deletion to records with
2424
+ * matching scope fields.
2425
+ */
2426
+ async function deleteScores(db, args) {
2427
+ if (args.scoreIds.length === 0) return;
2428
+ const conditions = [`scoreId IN (${args.scoreIds.map(() => "?").join(", ")})`];
2429
+ const params = [...args.scoreIds];
2430
+ if (args.organizationId !== void 0) {
2431
+ conditions.push("organizationId = ?");
2432
+ params.push(args.organizationId);
2433
+ }
2434
+ if (args.resourceId !== void 0) {
2435
+ conditions.push("resourceId = ?");
2436
+ params.push(args.resourceId);
2437
+ }
2438
+ await db.execute(`DELETE FROM score_events WHERE ${conditions.join(" AND ")}`, params);
2439
+ }
2398
2440
  /** Query score events with filtering, ordering, and pagination. */
2399
2441
  async function listScores(db, args) {
2400
2442
  const { mode, filters, pagination, orderBy, after, limit } = _mastra_core_storage.listScoresArgsSchema.parse(args);
@@ -2620,13 +2662,65 @@ const TRACE_FIELDS = {
2620
2662
  }
2621
2663
  };
2622
2664
  const SPAN_FIELDS = {
2665
+ name: {
2666
+ sql: "s.name",
2667
+ parameterType: "scalar"
2668
+ },
2623
2669
  spanType: {
2624
2670
  sql: "s.spanType",
2625
2671
  parameterType: "scalar"
2626
2672
  },
2673
+ model: {
2674
+ sql: "s.model",
2675
+ parameterType: "scalar"
2676
+ },
2677
+ provider: {
2678
+ sql: "s.provider",
2679
+ parameterType: "scalar"
2680
+ },
2681
+ startedAt: {
2682
+ sql: "s.startedAt",
2683
+ parameterType: "timestamp"
2684
+ },
2685
+ endedAt: {
2686
+ sql: "s.endedAt",
2687
+ parameterType: "timestamp"
2688
+ },
2689
+ durationMs: {
2690
+ sql: "s.durationMs",
2691
+ parameterType: "scalar"
2692
+ },
2693
+ status: {
2694
+ sql: "s.status",
2695
+ parameterType: "scalar"
2696
+ },
2627
2697
  error: {
2628
2698
  sql: "s.error",
2629
2699
  parameterType: "scalar"
2700
+ },
2701
+ entityType: {
2702
+ sql: "s.entityType",
2703
+ parameterType: "scalar"
2704
+ },
2705
+ entityId: {
2706
+ sql: "s.entityId",
2707
+ parameterType: "scalar"
2708
+ },
2709
+ entityName: {
2710
+ sql: "s.entityName",
2711
+ parameterType: "scalar"
2712
+ },
2713
+ entityVersionId: {
2714
+ sql: "s.entityVersionId",
2715
+ parameterType: "scalar"
2716
+ },
2717
+ parentEntityVersionId: {
2718
+ sql: "s.parentEntityVersionId",
2719
+ parameterType: "scalar"
2720
+ },
2721
+ rootEntityVersionId: {
2722
+ sql: "s.rootEntityVersionId",
2723
+ parameterType: "scalar"
2630
2724
  }
2631
2725
  };
2632
2726
  const SCORE_FIELDS = {
@@ -2634,9 +2728,37 @@ const SCORE_FIELDS = {
2634
2728
  sql: "s.scorerId",
2635
2729
  parameterType: "scalar"
2636
2730
  },
2731
+ scorerVersion: {
2732
+ sql: "s.scorerVersion",
2733
+ parameterType: "scalar"
2734
+ },
2735
+ scoreSource: {
2736
+ sql: "s.scoreSource",
2737
+ parameterType: "scalar"
2738
+ },
2637
2739
  score: {
2638
2740
  sql: "s.score",
2639
2741
  parameterType: "scalar"
2742
+ },
2743
+ timestamp: {
2744
+ sql: "s.timestamp",
2745
+ parameterType: "timestamp"
2746
+ },
2747
+ spanId: {
2748
+ sql: "s.spanId",
2749
+ parameterType: "scalar"
2750
+ },
2751
+ entityVersionId: {
2752
+ sql: "s.entityVersionId",
2753
+ parameterType: "scalar"
2754
+ },
2755
+ parentEntityVersionId: {
2756
+ sql: "s.parentEntityVersionId",
2757
+ parameterType: "scalar"
2758
+ },
2759
+ rootEntityVersionId: {
2760
+ sql: "s.rootEntityVersionId",
2761
+ parameterType: "scalar"
2640
2762
  }
2641
2763
  };
2642
2764
  const TRACE_SELECT = `
@@ -2658,12 +2780,15 @@ function fieldDefinition(registry, field) {
2658
2780
  function parameterSql(type) {
2659
2781
  return type === "timestamp" ? "CAST(? AS TIMESTAMP)" : "?";
2660
2782
  }
2661
- function compileScalarPredicate(predicate, registry) {
2783
+ function isMetadataField(field) {
2784
+ return field.startsWith("metadata.");
2785
+ }
2786
+ function compileScalarPredicate(predicate, registry, allowMetadata = false) {
2662
2787
  if (predicate.type === "boolean") {
2663
2788
  const values = [];
2664
2789
  return {
2665
2790
  sql: predicate.args.map((arg) => {
2666
- const compiled = compileScalarPredicate(arg, registry);
2791
+ const compiled = compileScalarPredicate(arg, registry, allowMetadata);
2667
2792
  values.push(...compiled.values);
2668
2793
  return `(${compiled.sql})`;
2669
2794
  }).join(predicate.operator === "and" ? " AND " : " OR "),
@@ -2671,26 +2796,45 @@ function compileScalarPredicate(predicate, registry) {
2671
2796
  };
2672
2797
  }
2673
2798
  if (predicate.type === "not") {
2674
- const compiled = compileScalarPredicate(predicate.arg, registry);
2799
+ const compiled = compileScalarPredicate(predicate.arg, registry, allowMetadata);
2675
2800
  return {
2676
2801
  sql: `NOT (${compiled.sql})`,
2677
2802
  values: compiled.values
2678
2803
  };
2679
2804
  }
2680
- const field = fieldDefinition(registry, predicate.field);
2805
+ let field;
2806
+ let fieldValues = [];
2807
+ if (isMetadataField(predicate.field)) {
2808
+ if (!allowMetadata) throw new Error(`Unsupported trusted trace-query field: ${predicate.field}`);
2809
+ const key = predicate.field.slice(9);
2810
+ const path = `$.${JSON.stringify(key)}`;
2811
+ field = {
2812
+ sql: `NULLIF(trim(CASE WHEN json_type(r.metadata, ?) = 'VARCHAR' THEN json_extract_string(r.metadata, ?) END), '')`,
2813
+ parameterType: "scalar"
2814
+ };
2815
+ fieldValues = [path, path];
2816
+ } else field = fieldDefinition(registry, predicate.field);
2681
2817
  if (predicate.type === "presence") return {
2682
2818
  sql: `${field.sql} IS ${predicate.operator === "exists" ? "NOT " : ""}NULL`,
2683
- values: []
2819
+ values: fieldValues
2684
2820
  };
2685
2821
  if (predicate.type === "membership") {
2686
2822
  const list = predicate.values.map(() => parameterSql(field.parameterType)).join(", ");
2687
2823
  if (predicate.operator === "in") return {
2688
2824
  sql: `${field.sql} IS NOT NULL AND ${field.sql} IN (${list})`,
2689
- values: predicate.values
2825
+ values: [
2826
+ ...fieldValues,
2827
+ ...fieldValues,
2828
+ ...predicate.values
2829
+ ]
2690
2830
  };
2691
2831
  return {
2692
2832
  sql: `${field.sql} IS NULL OR ${field.sql} NOT IN (${list})`,
2693
- values: predicate.values
2833
+ values: [
2834
+ ...fieldValues,
2835
+ ...fieldValues,
2836
+ ...predicate.values
2837
+ ]
2694
2838
  };
2695
2839
  }
2696
2840
  const parameter = parameterSql(field.parameterType);
@@ -2702,17 +2846,21 @@ function compileScalarPredicate(predicate, registry) {
2702
2846
  };
2703
2847
  if (predicate.operator === "eq") return {
2704
2848
  sql: `${field.sql} IS NOT DISTINCT FROM ${parameter}`,
2705
- values: [predicate.value]
2849
+ values: [...fieldValues, predicate.value]
2706
2850
  };
2707
2851
  if (predicate.operator === "ne") return {
2708
2852
  sql: `${field.sql} IS DISTINCT FROM ${parameter}`,
2709
- values: [predicate.value]
2853
+ values: [...fieldValues, predicate.value]
2710
2854
  };
2711
2855
  const operator = operators[predicate.operator];
2712
2856
  if (operator === void 0) throw new Error(`Unsupported trusted trace-query operator: ${predicate.operator}`);
2713
2857
  return {
2714
2858
  sql: `${field.sql} IS NOT NULL AND ${field.sql} ${operator} ${parameter}`,
2715
- values: [predicate.value]
2859
+ values: [
2860
+ ...fieldValues,
2861
+ ...fieldValues,
2862
+ predicate.value
2863
+ ]
2716
2864
  };
2717
2865
  }
2718
2866
  function compilePredicate(predicate) {
@@ -2748,7 +2896,7 @@ function compilePredicate(predicate) {
2748
2896
  values: compiled.values
2749
2897
  };
2750
2898
  }
2751
- return compileScalarPredicate(predicate, TRACE_FIELDS);
2899
+ return compileScalarPredicate(predicate, TRACE_FIELDS, true);
2752
2900
  }
2753
2901
  function collectRelatedCollections(predicate, collections = /* @__PURE__ */ new Set()) {
2754
2902
  if (!predicate) return collections;
@@ -2797,18 +2945,43 @@ function compileDuckDBTraceQuery(plan) {
2797
2945
  AND r.startedAt < CAST(? AS TIMESTAMP)
2798
2946
  )`
2799
2947
  ];
2800
- if (relatedCollections.has("spans")) ctes.push(`current_spans AS (
2801
- SELECT * EXCLUDE (currentRank)
2802
- FROM (
2803
- SELECT
2804
- e.*,
2805
- row_number() OVER (
2806
- PARTITION BY e.traceId, e.spanId
2807
- ORDER BY CASE WHEN e.endedAt IS NULL THEN 1 ELSE 0 END ASC, e.cursorId DESC
2808
- ) AS currentRank
2809
- FROM span_events e
2810
- INNER JOIN root_scope roots ON roots.traceId = e.traceId
2811
- )
2948
+ if (relatedCollections.has("spans")) ctes.push(`current_span_rows AS (
2949
+ SELECT
2950
+ e.*,
2951
+ coalesce(
2952
+ min(e.timestamp) FILTER (WHERE e.eventType = 'start') OVER (PARTITION BY e.traceId, e.spanId),
2953
+ min(e.timestamp) OVER (PARTITION BY e.traceId, e.spanId)
2954
+ ) AS startedAt,
2955
+ row_number() OVER (
2956
+ PARTITION BY e.traceId, e.spanId
2957
+ ORDER BY CASE WHEN e.endedAt IS NULL THEN 1 ELSE 0 END ASC, e.cursorId DESC
2958
+ ) AS currentRank
2959
+ FROM span_events e
2960
+ INNER JOIN root_scope roots ON roots.traceId = e.traceId
2961
+ ),
2962
+ current_spans AS (
2963
+ SELECT
2964
+ traceId,
2965
+ name,
2966
+ spanType,
2967
+ CASE
2968
+ WHEN json_type(attributes, '$.model') = 'VARCHAR' THEN json_extract_string(attributes, '$.model')
2969
+ END AS model,
2970
+ CASE
2971
+ WHEN json_type(attributes, '$.provider') = 'VARCHAR' THEN json_extract_string(attributes, '$.provider')
2972
+ END AS provider,
2973
+ startedAt,
2974
+ endedAt,
2975
+ date_diff('millisecond', startedAt, endedAt) AS durationMs,
2976
+ CASE WHEN error IS NOT NULL THEN 'error' ELSE 'success' END AS status,
2977
+ error,
2978
+ entityType,
2979
+ entityId,
2980
+ entityName,
2981
+ entityVersionId,
2982
+ parentEntityVersionId,
2983
+ rootEntityVersionId
2984
+ FROM current_span_rows
2812
2985
  WHERE currentRank = 1
2813
2986
  )`);
2814
2987
  if (relatedCollections.has("scores")) ctes.push(`current_scores AS (
@@ -2913,6 +3086,8 @@ const COLUMNS_SQL = [
2913
3086
  "entityId",
2914
3087
  "entityName",
2915
3088
  "entityVersionId",
3089
+ "parentEntityVersionId",
3090
+ "rootEntityVersionId",
2916
3091
  "userId",
2917
3092
  "organizationId",
2918
3093
  "resourceId",
@@ -2955,6 +3130,8 @@ const SPAN_RECONSTRUCT_SELECT = `
2955
3130
  ${argMaxNonNull("entityId")},
2956
3131
  ${argMaxNonNull("entityName")},
2957
3132
  ${argMaxNonNull("entityVersionId")},
3133
+ ${argMaxNonNull("parentEntityVersionId")},
3134
+ ${argMaxNonNull("rootEntityVersionId")},
2958
3135
  ${argMaxNonNull("userId")},
2959
3136
  ${argMaxNonNull("organizationId")},
2960
3137
  ${argMaxNonNull("resourceId")},
@@ -3122,6 +3299,8 @@ function rowToSpanRecord(row) {
3122
3299
  entityId: row.entityId ?? null,
3123
3300
  entityName: row.entityName ?? null,
3124
3301
  entityVersionId: row.entityVersionId ?? null,
3302
+ parentEntityVersionId: row.parentEntityVersionId ?? null,
3303
+ rootEntityVersionId: row.rootEntityVersionId ?? null,
3125
3304
  userId: row.userId ?? null,
3126
3305
  organizationId: row.organizationId ?? null,
3127
3306
  resourceId: row.resourceId ?? null,
@@ -3277,6 +3456,8 @@ function toValuesTuple(row) {
3277
3456
  v(row.entityId),
3278
3457
  v(row.entityName),
3279
3458
  v(row.entityVersionId),
3459
+ v(row.parentEntityVersionId),
3460
+ v(row.rootEntityVersionId),
3280
3461
  v(row.userId),
3281
3462
  v(row.organizationId),
3282
3463
  v(row.resourceId),
@@ -3319,6 +3500,8 @@ function createStartSpanRow(s) {
3319
3500
  entityId: s.entityId ?? null,
3320
3501
  entityName: s.entityName ?? null,
3321
3502
  entityVersionId: s.entityVersionId ?? null,
3503
+ parentEntityVersionId: s.parentEntityVersionId ?? null,
3504
+ rootEntityVersionId: s.rootEntityVersionId ?? null,
3322
3505
  userId: s.userId ?? null,
3323
3506
  organizationId: s.organizationId ?? null,
3324
3507
  resourceId: s.resourceId ?? null,
@@ -3356,6 +3539,8 @@ function createEndSpanRow(s) {
3356
3539
  entityId: s.entityId ?? null,
3357
3540
  entityName: s.entityName ?? null,
3358
3541
  entityVersionId: s.entityVersionId ?? null,
3542
+ parentEntityVersionId: s.parentEntityVersionId ?? null,
3543
+ rootEntityVersionId: s.rootEntityVersionId ?? null,
3359
3544
  userId: s.userId ?? null,
3360
3545
  organizationId: s.organizationId ?? null,
3361
3546
  resourceId: s.resourceId ?? null,
@@ -4222,6 +4407,9 @@ var ObservabilityStorageDuckDB = class extends _mastra_core_storage.Observabilit
4222
4407
  async batchCreateScores(args) {
4223
4408
  return batchCreateScores(this.db, args);
4224
4409
  }
4410
+ async deleteScores(args) {
4411
+ return deleteScores(this.db, args);
4412
+ }
4225
4413
  async listScores(args) {
4226
4414
  return listScores(this.db, args);
4227
4415
  }
@@ -4246,6 +4434,9 @@ var ObservabilityStorageDuckDB = class extends _mastra_core_storage.Observabilit
4246
4434
  async batchCreateFeedback(args) {
4247
4435
  return batchCreateFeedback(this.db, args);
4248
4436
  }
4437
+ async deleteFeedback(args) {
4438
+ return deleteFeedback(this.db, args);
4439
+ }
4249
4440
  async listFeedback(args) {
4250
4441
  return listFeedback(this.db, args);
4251
4442
  }
@@ -4268,4 +4459,4 @@ var ObservabilityStorageDuckDB = class extends _mastra_core_storage.Observabilit
4268
4459
  //#endregion
4269
4460
  exports.ObservabilityStorageDuckDB = ObservabilityStorageDuckDB;
4270
4461
 
4271
- //# sourceMappingURL=observability-yLoG0tl3.cjs.map
4462
+ //# sourceMappingURL=observability-DlMgmuxw.cjs.map