@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.
@@ -52,6 +52,8 @@ CREATE TABLE IF NOT EXISTS span_events (
52
52
  entityId VARCHAR,
53
53
  entityName VARCHAR,
54
54
  entityVersionId VARCHAR,
55
+ parentEntityVersionId VARCHAR,
56
+ rootEntityVersionId VARCHAR,
55
57
 
56
58
  -- Context
57
59
  userId VARCHAR,
@@ -317,6 +319,8 @@ const ALL_MIGRATIONS = [
317
319
  `CREATE SEQUENCE IF NOT EXISTS feedback_events_cursor_id_seq START 1`,
318
320
  `ALTER TABLE span_events ADD COLUMN IF NOT EXISTS cursorId BIGINT`,
319
321
  `ALTER TABLE span_events ADD COLUMN IF NOT EXISTS entityVersionId VARCHAR`,
322
+ `ALTER TABLE span_events ADD COLUMN IF NOT EXISTS parentEntityVersionId VARCHAR`,
323
+ `ALTER TABLE span_events ADD COLUMN IF NOT EXISTS rootEntityVersionId VARCHAR`,
320
324
  `ALTER TABLE metric_events ADD COLUMN IF NOT EXISTS cursorId BIGINT`,
321
325
  `ALTER TABLE metric_events ADD COLUMN IF NOT EXISTS entityVersionId VARCHAR`,
322
326
  `ALTER TABLE metric_events ADD COLUMN IF NOT EXISTS parentEntityVersionId VARCHAR`,
@@ -1016,6 +1020,25 @@ async function batchCreateFeedback(db, args) {
1016
1020
  VALUES ${tuples.join(",\n ")}
1017
1021
  ON CONFLICT DO NOTHING`);
1018
1022
  }
1023
+ /**
1024
+ * Delete feedback events by feedbackId. Optional `organizationId` and
1025
+ * `resourceId` values are ANDed into the predicate to restrict deletion to
1026
+ * records with matching scope fields.
1027
+ */
1028
+ async function deleteFeedback(db, args) {
1029
+ if (args.feedbackIds.length === 0) return;
1030
+ const conditions = [`feedbackId IN (${args.feedbackIds.map(() => "?").join(", ")})`];
1031
+ const params = [...args.feedbackIds];
1032
+ if (args.organizationId !== void 0) {
1033
+ conditions.push("organizationId = ?");
1034
+ params.push(args.organizationId);
1035
+ }
1036
+ if (args.resourceId !== void 0) {
1037
+ conditions.push("resourceId = ?");
1038
+ params.push(args.resourceId);
1039
+ }
1040
+ await db.execute(`DELETE FROM feedback_events WHERE ${conditions.join(" AND ")}`, params);
1041
+ }
1019
1042
  /** Update the review workflow status of a single feedback event. */
1020
1043
  async function updateFeedbackReviewStatus(db, args) {
1021
1044
  const { feedbackId, reviewStatus } = parseUpdateFeedbackReviewStatusArgs(args);
@@ -2373,6 +2396,25 @@ async function batchCreateScores(db, args) {
2373
2396
  VALUES ${tuples.join(",\n ")}
2374
2397
  ${SCORE_UPSERT_CLAUSE}`);
2375
2398
  }
2399
+ /**
2400
+ * Delete score events by scoreId. Optional `organizationId` and `resourceId`
2401
+ * values are ANDed into the predicate to restrict deletion to records with
2402
+ * matching scope fields.
2403
+ */
2404
+ async function deleteScores(db, args) {
2405
+ if (args.scoreIds.length === 0) return;
2406
+ const conditions = [`scoreId IN (${args.scoreIds.map(() => "?").join(", ")})`];
2407
+ const params = [...args.scoreIds];
2408
+ if (args.organizationId !== void 0) {
2409
+ conditions.push("organizationId = ?");
2410
+ params.push(args.organizationId);
2411
+ }
2412
+ if (args.resourceId !== void 0) {
2413
+ conditions.push("resourceId = ?");
2414
+ params.push(args.resourceId);
2415
+ }
2416
+ await db.execute(`DELETE FROM score_events WHERE ${conditions.join(" AND ")}`, params);
2417
+ }
2376
2418
  /** Query score events with filtering, ordering, and pagination. */
2377
2419
  async function listScores(db, args) {
2378
2420
  const { mode, filters, pagination, orderBy, after, limit } = listScoresArgsSchema.parse(args);
@@ -2598,13 +2640,65 @@ const TRACE_FIELDS = {
2598
2640
  }
2599
2641
  };
2600
2642
  const SPAN_FIELDS = {
2643
+ name: {
2644
+ sql: "s.name",
2645
+ parameterType: "scalar"
2646
+ },
2601
2647
  spanType: {
2602
2648
  sql: "s.spanType",
2603
2649
  parameterType: "scalar"
2604
2650
  },
2651
+ model: {
2652
+ sql: "s.model",
2653
+ parameterType: "scalar"
2654
+ },
2655
+ provider: {
2656
+ sql: "s.provider",
2657
+ parameterType: "scalar"
2658
+ },
2659
+ startedAt: {
2660
+ sql: "s.startedAt",
2661
+ parameterType: "timestamp"
2662
+ },
2663
+ endedAt: {
2664
+ sql: "s.endedAt",
2665
+ parameterType: "timestamp"
2666
+ },
2667
+ durationMs: {
2668
+ sql: "s.durationMs",
2669
+ parameterType: "scalar"
2670
+ },
2671
+ status: {
2672
+ sql: "s.status",
2673
+ parameterType: "scalar"
2674
+ },
2605
2675
  error: {
2606
2676
  sql: "s.error",
2607
2677
  parameterType: "scalar"
2678
+ },
2679
+ entityType: {
2680
+ sql: "s.entityType",
2681
+ parameterType: "scalar"
2682
+ },
2683
+ entityId: {
2684
+ sql: "s.entityId",
2685
+ parameterType: "scalar"
2686
+ },
2687
+ entityName: {
2688
+ sql: "s.entityName",
2689
+ parameterType: "scalar"
2690
+ },
2691
+ entityVersionId: {
2692
+ sql: "s.entityVersionId",
2693
+ parameterType: "scalar"
2694
+ },
2695
+ parentEntityVersionId: {
2696
+ sql: "s.parentEntityVersionId",
2697
+ parameterType: "scalar"
2698
+ },
2699
+ rootEntityVersionId: {
2700
+ sql: "s.rootEntityVersionId",
2701
+ parameterType: "scalar"
2608
2702
  }
2609
2703
  };
2610
2704
  const SCORE_FIELDS = {
@@ -2612,9 +2706,37 @@ const SCORE_FIELDS = {
2612
2706
  sql: "s.scorerId",
2613
2707
  parameterType: "scalar"
2614
2708
  },
2709
+ scorerVersion: {
2710
+ sql: "s.scorerVersion",
2711
+ parameterType: "scalar"
2712
+ },
2713
+ scoreSource: {
2714
+ sql: "s.scoreSource",
2715
+ parameterType: "scalar"
2716
+ },
2615
2717
  score: {
2616
2718
  sql: "s.score",
2617
2719
  parameterType: "scalar"
2720
+ },
2721
+ timestamp: {
2722
+ sql: "s.timestamp",
2723
+ parameterType: "timestamp"
2724
+ },
2725
+ spanId: {
2726
+ sql: "s.spanId",
2727
+ parameterType: "scalar"
2728
+ },
2729
+ entityVersionId: {
2730
+ sql: "s.entityVersionId",
2731
+ parameterType: "scalar"
2732
+ },
2733
+ parentEntityVersionId: {
2734
+ sql: "s.parentEntityVersionId",
2735
+ parameterType: "scalar"
2736
+ },
2737
+ rootEntityVersionId: {
2738
+ sql: "s.rootEntityVersionId",
2739
+ parameterType: "scalar"
2618
2740
  }
2619
2741
  };
2620
2742
  const TRACE_SELECT = `
@@ -2636,12 +2758,15 @@ function fieldDefinition(registry, field) {
2636
2758
  function parameterSql(type) {
2637
2759
  return type === "timestamp" ? "CAST(? AS TIMESTAMP)" : "?";
2638
2760
  }
2639
- function compileScalarPredicate(predicate, registry) {
2761
+ function isMetadataField(field) {
2762
+ return field.startsWith("metadata.");
2763
+ }
2764
+ function compileScalarPredicate(predicate, registry, allowMetadata = false) {
2640
2765
  if (predicate.type === "boolean") {
2641
2766
  const values = [];
2642
2767
  return {
2643
2768
  sql: predicate.args.map((arg) => {
2644
- const compiled = compileScalarPredicate(arg, registry);
2769
+ const compiled = compileScalarPredicate(arg, registry, allowMetadata);
2645
2770
  values.push(...compiled.values);
2646
2771
  return `(${compiled.sql})`;
2647
2772
  }).join(predicate.operator === "and" ? " AND " : " OR "),
@@ -2649,26 +2774,45 @@ function compileScalarPredicate(predicate, registry) {
2649
2774
  };
2650
2775
  }
2651
2776
  if (predicate.type === "not") {
2652
- const compiled = compileScalarPredicate(predicate.arg, registry);
2777
+ const compiled = compileScalarPredicate(predicate.arg, registry, allowMetadata);
2653
2778
  return {
2654
2779
  sql: `NOT (${compiled.sql})`,
2655
2780
  values: compiled.values
2656
2781
  };
2657
2782
  }
2658
- const field = fieldDefinition(registry, predicate.field);
2783
+ let field;
2784
+ let fieldValues = [];
2785
+ if (isMetadataField(predicate.field)) {
2786
+ if (!allowMetadata) throw new Error(`Unsupported trusted trace-query field: ${predicate.field}`);
2787
+ const key = predicate.field.slice(9);
2788
+ const path = `$.${JSON.stringify(key)}`;
2789
+ field = {
2790
+ sql: `NULLIF(trim(CASE WHEN json_type(r.metadata, ?) = 'VARCHAR' THEN json_extract_string(r.metadata, ?) END), '')`,
2791
+ parameterType: "scalar"
2792
+ };
2793
+ fieldValues = [path, path];
2794
+ } else field = fieldDefinition(registry, predicate.field);
2659
2795
  if (predicate.type === "presence") return {
2660
2796
  sql: `${field.sql} IS ${predicate.operator === "exists" ? "NOT " : ""}NULL`,
2661
- values: []
2797
+ values: fieldValues
2662
2798
  };
2663
2799
  if (predicate.type === "membership") {
2664
2800
  const list = predicate.values.map(() => parameterSql(field.parameterType)).join(", ");
2665
2801
  if (predicate.operator === "in") return {
2666
2802
  sql: `${field.sql} IS NOT NULL AND ${field.sql} IN (${list})`,
2667
- values: predicate.values
2803
+ values: [
2804
+ ...fieldValues,
2805
+ ...fieldValues,
2806
+ ...predicate.values
2807
+ ]
2668
2808
  };
2669
2809
  return {
2670
2810
  sql: `${field.sql} IS NULL OR ${field.sql} NOT IN (${list})`,
2671
- values: predicate.values
2811
+ values: [
2812
+ ...fieldValues,
2813
+ ...fieldValues,
2814
+ ...predicate.values
2815
+ ]
2672
2816
  };
2673
2817
  }
2674
2818
  const parameter = parameterSql(field.parameterType);
@@ -2680,17 +2824,21 @@ function compileScalarPredicate(predicate, registry) {
2680
2824
  };
2681
2825
  if (predicate.operator === "eq") return {
2682
2826
  sql: `${field.sql} IS NOT DISTINCT FROM ${parameter}`,
2683
- values: [predicate.value]
2827
+ values: [...fieldValues, predicate.value]
2684
2828
  };
2685
2829
  if (predicate.operator === "ne") return {
2686
2830
  sql: `${field.sql} IS DISTINCT FROM ${parameter}`,
2687
- values: [predicate.value]
2831
+ values: [...fieldValues, predicate.value]
2688
2832
  };
2689
2833
  const operator = operators[predicate.operator];
2690
2834
  if (operator === void 0) throw new Error(`Unsupported trusted trace-query operator: ${predicate.operator}`);
2691
2835
  return {
2692
2836
  sql: `${field.sql} IS NOT NULL AND ${field.sql} ${operator} ${parameter}`,
2693
- values: [predicate.value]
2837
+ values: [
2838
+ ...fieldValues,
2839
+ ...fieldValues,
2840
+ predicate.value
2841
+ ]
2694
2842
  };
2695
2843
  }
2696
2844
  function compilePredicate(predicate) {
@@ -2726,7 +2874,7 @@ function compilePredicate(predicate) {
2726
2874
  values: compiled.values
2727
2875
  };
2728
2876
  }
2729
- return compileScalarPredicate(predicate, TRACE_FIELDS);
2877
+ return compileScalarPredicate(predicate, TRACE_FIELDS, true);
2730
2878
  }
2731
2879
  function collectRelatedCollections(predicate, collections = /* @__PURE__ */ new Set()) {
2732
2880
  if (!predicate) return collections;
@@ -2775,18 +2923,43 @@ function compileDuckDBTraceQuery(plan) {
2775
2923
  AND r.startedAt < CAST(? AS TIMESTAMP)
2776
2924
  )`
2777
2925
  ];
2778
- if (relatedCollections.has("spans")) ctes.push(`current_spans AS (
2779
- SELECT * EXCLUDE (currentRank)
2780
- FROM (
2781
- SELECT
2782
- e.*,
2783
- row_number() OVER (
2784
- PARTITION BY e.traceId, e.spanId
2785
- ORDER BY CASE WHEN e.endedAt IS NULL THEN 1 ELSE 0 END ASC, e.cursorId DESC
2786
- ) AS currentRank
2787
- FROM span_events e
2788
- INNER JOIN root_scope roots ON roots.traceId = e.traceId
2789
- )
2926
+ if (relatedCollections.has("spans")) ctes.push(`current_span_rows AS (
2927
+ SELECT
2928
+ e.*,
2929
+ coalesce(
2930
+ min(e.timestamp) FILTER (WHERE e.eventType = 'start') OVER (PARTITION BY e.traceId, e.spanId),
2931
+ min(e.timestamp) OVER (PARTITION BY e.traceId, e.spanId)
2932
+ ) AS startedAt,
2933
+ row_number() OVER (
2934
+ PARTITION BY e.traceId, e.spanId
2935
+ ORDER BY CASE WHEN e.endedAt IS NULL THEN 1 ELSE 0 END ASC, e.cursorId DESC
2936
+ ) AS currentRank
2937
+ FROM span_events e
2938
+ INNER JOIN root_scope roots ON roots.traceId = e.traceId
2939
+ ),
2940
+ current_spans AS (
2941
+ SELECT
2942
+ traceId,
2943
+ name,
2944
+ spanType,
2945
+ CASE
2946
+ WHEN json_type(attributes, '$.model') = 'VARCHAR' THEN json_extract_string(attributes, '$.model')
2947
+ END AS model,
2948
+ CASE
2949
+ WHEN json_type(attributes, '$.provider') = 'VARCHAR' THEN json_extract_string(attributes, '$.provider')
2950
+ END AS provider,
2951
+ startedAt,
2952
+ endedAt,
2953
+ date_diff('millisecond', startedAt, endedAt) AS durationMs,
2954
+ CASE WHEN error IS NOT NULL THEN 'error' ELSE 'success' END AS status,
2955
+ error,
2956
+ entityType,
2957
+ entityId,
2958
+ entityName,
2959
+ entityVersionId,
2960
+ parentEntityVersionId,
2961
+ rootEntityVersionId
2962
+ FROM current_span_rows
2790
2963
  WHERE currentRank = 1
2791
2964
  )`);
2792
2965
  if (relatedCollections.has("scores")) ctes.push(`current_scores AS (
@@ -2891,6 +3064,8 @@ const COLUMNS_SQL = [
2891
3064
  "entityId",
2892
3065
  "entityName",
2893
3066
  "entityVersionId",
3067
+ "parentEntityVersionId",
3068
+ "rootEntityVersionId",
2894
3069
  "userId",
2895
3070
  "organizationId",
2896
3071
  "resourceId",
@@ -2933,6 +3108,8 @@ const SPAN_RECONSTRUCT_SELECT = `
2933
3108
  ${argMaxNonNull("entityId")},
2934
3109
  ${argMaxNonNull("entityName")},
2935
3110
  ${argMaxNonNull("entityVersionId")},
3111
+ ${argMaxNonNull("parentEntityVersionId")},
3112
+ ${argMaxNonNull("rootEntityVersionId")},
2936
3113
  ${argMaxNonNull("userId")},
2937
3114
  ${argMaxNonNull("organizationId")},
2938
3115
  ${argMaxNonNull("resourceId")},
@@ -3100,6 +3277,8 @@ function rowToSpanRecord(row) {
3100
3277
  entityId: row.entityId ?? null,
3101
3278
  entityName: row.entityName ?? null,
3102
3279
  entityVersionId: row.entityVersionId ?? null,
3280
+ parentEntityVersionId: row.parentEntityVersionId ?? null,
3281
+ rootEntityVersionId: row.rootEntityVersionId ?? null,
3103
3282
  userId: row.userId ?? null,
3104
3283
  organizationId: row.organizationId ?? null,
3105
3284
  resourceId: row.resourceId ?? null,
@@ -3255,6 +3434,8 @@ function toValuesTuple(row) {
3255
3434
  v(row.entityId),
3256
3435
  v(row.entityName),
3257
3436
  v(row.entityVersionId),
3437
+ v(row.parentEntityVersionId),
3438
+ v(row.rootEntityVersionId),
3258
3439
  v(row.userId),
3259
3440
  v(row.organizationId),
3260
3441
  v(row.resourceId),
@@ -3297,6 +3478,8 @@ function createStartSpanRow(s) {
3297
3478
  entityId: s.entityId ?? null,
3298
3479
  entityName: s.entityName ?? null,
3299
3480
  entityVersionId: s.entityVersionId ?? null,
3481
+ parentEntityVersionId: s.parentEntityVersionId ?? null,
3482
+ rootEntityVersionId: s.rootEntityVersionId ?? null,
3300
3483
  userId: s.userId ?? null,
3301
3484
  organizationId: s.organizationId ?? null,
3302
3485
  resourceId: s.resourceId ?? null,
@@ -3334,6 +3517,8 @@ function createEndSpanRow(s) {
3334
3517
  entityId: s.entityId ?? null,
3335
3518
  entityName: s.entityName ?? null,
3336
3519
  entityVersionId: s.entityVersionId ?? null,
3520
+ parentEntityVersionId: s.parentEntityVersionId ?? null,
3521
+ rootEntityVersionId: s.rootEntityVersionId ?? null,
3337
3522
  userId: s.userId ?? null,
3338
3523
  organizationId: s.organizationId ?? null,
3339
3524
  resourceId: s.resourceId ?? null,
@@ -4200,6 +4385,9 @@ var ObservabilityStorageDuckDB = class extends ObservabilityStorage {
4200
4385
  async batchCreateScores(args) {
4201
4386
  return batchCreateScores(this.db, args);
4202
4387
  }
4388
+ async deleteScores(args) {
4389
+ return deleteScores(this.db, args);
4390
+ }
4203
4391
  async listScores(args) {
4204
4392
  return listScores(this.db, args);
4205
4393
  }
@@ -4224,6 +4412,9 @@ var ObservabilityStorageDuckDB = class extends ObservabilityStorage {
4224
4412
  async batchCreateFeedback(args) {
4225
4413
  return batchCreateFeedback(this.db, args);
4226
4414
  }
4415
+ async deleteFeedback(args) {
4416
+ return deleteFeedback(this.db, args);
4417
+ }
4227
4418
  async listFeedback(args) {
4228
4419
  return listFeedback(this.db, args);
4229
4420
  }
@@ -4246,4 +4437,4 @@ var ObservabilityStorageDuckDB = class extends ObservabilityStorage {
4246
4437
  //#endregion
4247
4438
  export { ObservabilityStorageDuckDB };
4248
4439
 
4249
- //# sourceMappingURL=observability-Bt92lKRG.js.map
4440
+ //# sourceMappingURL=observability-2dvzwZpP.js.map