@mastra/duckdb 1.6.4 → 1.7.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.
Files changed (30) hide show
  1. package/dist/{db-TBEcMD49.cjs → db-CJBcanx4.cjs} +27 -1
  2. package/dist/db-CJBcanx4.cjs.map +1 -0
  3. package/dist/{db-Dl0fY488.js → db-b2jufH0V.js} +27 -1
  4. package/dist/db-b2jufH0V.js.map +1 -0
  5. package/dist/docs/SKILL.md +1 -1
  6. package/dist/docs/assets/SOURCE_MAP.json +1 -1
  7. package/dist/index.cjs +12 -4
  8. package/dist/index.cjs.map +1 -1
  9. package/dist/index.js +12 -4
  10. package/dist/index.js.map +1 -1
  11. package/dist/{observability-CT5eidI9.js → observability-Bt92lKRG.js} +396 -8
  12. package/dist/observability-Bt92lKRG.js.map +1 -0
  13. package/dist/{observability-CYOty2wB.cjs → observability-yLoG0tl3.cjs} +418 -8
  14. package/dist/observability-yLoG0tl3.cjs.map +1 -0
  15. package/dist/storage/db/index.d.ts +5 -0
  16. package/dist/storage/db/index.d.ts.map +1 -1
  17. package/dist/storage/domains/observability/index.d.ts +3 -2
  18. package/dist/storage/domains/observability/index.d.ts.map +1 -1
  19. package/dist/storage/domains/observability/scores.d.ts.map +1 -1
  20. package/dist/storage/domains/observability/trace-query.d.ts +9 -0
  21. package/dist/storage/domains/observability/trace-query.d.ts.map +1 -0
  22. package/dist/storage/domains/observability/tracing.d.ts +7 -1
  23. package/dist/storage/domains/observability/tracing.d.ts.map +1 -1
  24. package/dist/storage/index.d.ts +1 -0
  25. package/dist/storage/index.d.ts.map +1 -1
  26. package/package.json +3 -3
  27. package/dist/db-Dl0fY488.js.map +0 -1
  28. package/dist/db-TBEcMD49.cjs.map +0 -1
  29. package/dist/observability-CT5eidI9.js.map +0 -1
  30. package/dist/observability-CYOty2wB.cjs.map +0 -1
@@ -1,6 +1,29 @@
1
- const require_db = require("./db-TBEcMD49.cjs");
1
+ //#region \0rolldown/runtime.js
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
10
+ key = keys[i];
11
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
+ get: ((k) => from[k]).bind(null, key),
13
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
14
+ });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
19
+ value: mod,
20
+ enumerable: true
21
+ }) : target, mod));
22
+ //#endregion
23
+ const require_db = require("./db-CJBcanx4.cjs");
2
24
  let _mastra_core_error = require("@mastra/core/error");
3
25
  let _mastra_core_storage = require("@mastra/core/storage");
26
+ _mastra_core_storage = __toESM(_mastra_core_storage, 1);
4
27
  let _mastra_core_features = require("@mastra/core/features");
5
28
  let _mastra_core_observability = require("@mastra/core/observability");
6
29
  let _mastra_core_utils = require("@mastra/core/utils");
@@ -2070,6 +2093,43 @@ async function migrateSignalTables(db, logger) {
2070
2093
  }
2071
2094
  //#endregion
2072
2095
  //#region src/storage/domains/observability/scores.ts
2096
+ const SCORE_UPSERT_CLAUSE = `ON CONFLICT (scoreId) DO UPDATE SET ${[
2097
+ "timestamp",
2098
+ "traceId",
2099
+ "spanId",
2100
+ "experimentId",
2101
+ "scoreTraceId",
2102
+ "entityType",
2103
+ "entityId",
2104
+ "entityName",
2105
+ "entityVersionId",
2106
+ "parentEntityVersionId",
2107
+ "parentEntityType",
2108
+ "parentEntityId",
2109
+ "parentEntityName",
2110
+ "rootEntityVersionId",
2111
+ "rootEntityType",
2112
+ "rootEntityId",
2113
+ "rootEntityName",
2114
+ "userId",
2115
+ "organizationId",
2116
+ "resourceId",
2117
+ "runId",
2118
+ "sessionId",
2119
+ "threadId",
2120
+ "requestId",
2121
+ "environment",
2122
+ "executionSource",
2123
+ "serviceName",
2124
+ "scorerId",
2125
+ "scorerVersion",
2126
+ "scoreSource",
2127
+ "score",
2128
+ "reason",
2129
+ "tags",
2130
+ "metadata",
2131
+ "scope"
2132
+ ].map((column) => `${column} = excluded.${column}`).join(", ")}`;
2073
2133
  const SCORE_GROUP_BY_COLUMNS = /* @__PURE__ */ new Set([
2074
2134
  "timestamp",
2075
2135
  "traceId",
@@ -2278,7 +2338,7 @@ async function createScore(db, args) {
2278
2338
  jsonV(s.metadata),
2279
2339
  jsonV(s.scope ?? null)
2280
2340
  ].join(", ")})
2281
- ON CONFLICT DO NOTHING`);
2341
+ ${SCORE_UPSERT_CLAUSE}`);
2282
2342
  }
2283
2343
  /** Insert multiple score events in a single statement. */
2284
2344
  async function batchCreateScores(db, args) {
@@ -2333,7 +2393,7 @@ async function batchCreateScores(db, args) {
2333
2393
  scorerId, scorerVersion, scoreSource, score, reason, tags, metadata, scope
2334
2394
  )
2335
2395
  VALUES ${tuples.join(",\n ")}
2336
- ON CONFLICT DO NOTHING`);
2396
+ ${SCORE_UPSERT_CLAUSE}`);
2337
2397
  }
2338
2398
  /** Query score events with filtering, ordering, and pagination. */
2339
2399
  async function listScores(db, args) {
@@ -2519,6 +2579,323 @@ async function getScorePercentiles(db, args) {
2519
2579
  return { series };
2520
2580
  }
2521
2581
  //#endregion
2582
+ //#region src/storage/domains/observability/trace-query.ts
2583
+ const TRACE_STATUS_SQL = `CASE WHEN r.error IS NOT NULL THEN 'error' ELSE 'success' END`;
2584
+ const TRACE_FIELDS = {
2585
+ traceId: {
2586
+ sql: "r.traceId",
2587
+ parameterType: "scalar"
2588
+ },
2589
+ threadId: {
2590
+ sql: "r.threadId",
2591
+ parameterType: "scalar"
2592
+ },
2593
+ resourceId: {
2594
+ sql: "r.resourceId",
2595
+ parameterType: "scalar"
2596
+ },
2597
+ startedAt: {
2598
+ sql: "r.startedAt",
2599
+ parameterType: "timestamp"
2600
+ },
2601
+ endedAt: {
2602
+ sql: "r.endedAt",
2603
+ parameterType: "timestamp"
2604
+ },
2605
+ entityName: {
2606
+ sql: "r.entityName",
2607
+ parameterType: "scalar"
2608
+ },
2609
+ entityType: {
2610
+ sql: "r.entityType",
2611
+ parameterType: "scalar"
2612
+ },
2613
+ environment: {
2614
+ sql: "r.environment",
2615
+ parameterType: "scalar"
2616
+ },
2617
+ status: {
2618
+ sql: TRACE_STATUS_SQL,
2619
+ parameterType: "scalar"
2620
+ }
2621
+ };
2622
+ const SPAN_FIELDS = {
2623
+ spanType: {
2624
+ sql: "s.spanType",
2625
+ parameterType: "scalar"
2626
+ },
2627
+ error: {
2628
+ sql: "s.error",
2629
+ parameterType: "scalar"
2630
+ }
2631
+ };
2632
+ const SCORE_FIELDS = {
2633
+ scorerId: {
2634
+ sql: "s.scorerId",
2635
+ parameterType: "scalar"
2636
+ },
2637
+ score: {
2638
+ sql: "s.score",
2639
+ parameterType: "scalar"
2640
+ }
2641
+ };
2642
+ const TRACE_SELECT = `
2643
+ r.traceId AS traceId,
2644
+ r.spanId AS rootSpanId,
2645
+ r.threadId AS threadId,
2646
+ r.resourceId AS resourceId,
2647
+ r.startedAt AS startedAt,
2648
+ r.endedAt AS endedAt,
2649
+ r.entityName AS entityName,
2650
+ r.entityType AS entityType,
2651
+ r.environment AS environment,
2652
+ ${TRACE_STATUS_SQL} AS status`;
2653
+ function fieldDefinition(registry, field) {
2654
+ const definition = registry[field];
2655
+ if (definition === void 0) throw new Error(`Unsupported trusted trace-query field: ${field}`);
2656
+ return definition;
2657
+ }
2658
+ function parameterSql(type) {
2659
+ return type === "timestamp" ? "CAST(? AS TIMESTAMP)" : "?";
2660
+ }
2661
+ function compileScalarPredicate(predicate, registry) {
2662
+ if (predicate.type === "boolean") {
2663
+ const values = [];
2664
+ return {
2665
+ sql: predicate.args.map((arg) => {
2666
+ const compiled = compileScalarPredicate(arg, registry);
2667
+ values.push(...compiled.values);
2668
+ return `(${compiled.sql})`;
2669
+ }).join(predicate.operator === "and" ? " AND " : " OR "),
2670
+ values
2671
+ };
2672
+ }
2673
+ if (predicate.type === "not") {
2674
+ const compiled = compileScalarPredicate(predicate.arg, registry);
2675
+ return {
2676
+ sql: `NOT (${compiled.sql})`,
2677
+ values: compiled.values
2678
+ };
2679
+ }
2680
+ const field = fieldDefinition(registry, predicate.field);
2681
+ if (predicate.type === "presence") return {
2682
+ sql: `${field.sql} IS ${predicate.operator === "exists" ? "NOT " : ""}NULL`,
2683
+ values: []
2684
+ };
2685
+ if (predicate.type === "membership") {
2686
+ const list = predicate.values.map(() => parameterSql(field.parameterType)).join(", ");
2687
+ if (predicate.operator === "in") return {
2688
+ sql: `${field.sql} IS NOT NULL AND ${field.sql} IN (${list})`,
2689
+ values: predicate.values
2690
+ };
2691
+ return {
2692
+ sql: `${field.sql} IS NULL OR ${field.sql} NOT IN (${list})`,
2693
+ values: predicate.values
2694
+ };
2695
+ }
2696
+ const parameter = parameterSql(field.parameterType);
2697
+ const operators = {
2698
+ lt: "<",
2699
+ lte: "<=",
2700
+ gt: ">",
2701
+ gte: ">="
2702
+ };
2703
+ if (predicate.operator === "eq") return {
2704
+ sql: `${field.sql} IS NOT DISTINCT FROM ${parameter}`,
2705
+ values: [predicate.value]
2706
+ };
2707
+ if (predicate.operator === "ne") return {
2708
+ sql: `${field.sql} IS DISTINCT FROM ${parameter}`,
2709
+ values: [predicate.value]
2710
+ };
2711
+ const operator = operators[predicate.operator];
2712
+ if (operator === void 0) throw new Error(`Unsupported trusted trace-query operator: ${predicate.operator}`);
2713
+ return {
2714
+ sql: `${field.sql} IS NOT NULL AND ${field.sql} ${operator} ${parameter}`,
2715
+ values: [predicate.value]
2716
+ };
2717
+ }
2718
+ function compilePredicate(predicate) {
2719
+ if (predicate.type === "relation") {
2720
+ const registry = predicate.collection === "spans" ? SPAN_FIELDS : SCORE_FIELDS;
2721
+ const compiled = compileScalarPredicate(predicate.predicate, registry);
2722
+ const existence = `EXISTS (
2723
+ SELECT 1 FROM ${predicate.collection === "spans" ? "current_spans" : "current_scores"} s
2724
+ WHERE s.traceId IS NOT NULL
2725
+ AND s.traceId = r.traceId
2726
+ AND (${compiled.sql})
2727
+ )`;
2728
+ return {
2729
+ sql: predicate.quantifier === "some" ? existence : `NOT ${existence}`,
2730
+ values: compiled.values
2731
+ };
2732
+ }
2733
+ if (predicate.type === "boolean") {
2734
+ const values = [];
2735
+ return {
2736
+ sql: predicate.args.map((arg) => {
2737
+ const compiled = compilePredicate(arg);
2738
+ values.push(...compiled.values);
2739
+ return `(${compiled.sql})`;
2740
+ }).join(predicate.operator === "and" ? " AND " : " OR "),
2741
+ values
2742
+ };
2743
+ }
2744
+ if (predicate.type === "not") {
2745
+ const compiled = compilePredicate(predicate.arg);
2746
+ return {
2747
+ sql: `NOT (${compiled.sql})`,
2748
+ values: compiled.values
2749
+ };
2750
+ }
2751
+ return compileScalarPredicate(predicate, TRACE_FIELDS);
2752
+ }
2753
+ function collectRelatedCollections(predicate, collections = /* @__PURE__ */ new Set()) {
2754
+ if (!predicate) return collections;
2755
+ if (predicate.type === "relation") collections.add(predicate.collection);
2756
+ else if (predicate.type === "boolean") for (const arg of predicate.args) collectRelatedCollections(arg, collections);
2757
+ else if (predicate.type === "not") collectRelatedCollections(predicate.arg, collections);
2758
+ return collections;
2759
+ }
2760
+ function compileDuckDBTraceQuery(plan) {
2761
+ const values = [plan.timeRange.from, plan.timeRange.to];
2762
+ const conditions = [
2763
+ `r.endedAt IS NOT NULL`,
2764
+ `r.startedAt >= CAST(? AS TIMESTAMP)`,
2765
+ `r.startedAt < CAST(? AS TIMESTAMP)`
2766
+ ];
2767
+ if (plan.where) {
2768
+ const predicate = compilePredicate(plan.where);
2769
+ conditions.push(`(${predicate.sql})`);
2770
+ values.push(...predicate.values);
2771
+ }
2772
+ const relatedCollections = collectRelatedCollections(plan.where);
2773
+ const ctes = [
2774
+ `root_events AS (
2775
+ SELECT
2776
+ *,
2777
+ CASE
2778
+ WHEN eventType = 'start' THEN timestamp
2779
+ ELSE lag(timestamp) OVER (PARTITION BY traceId, spanId ORDER BY cursorId)
2780
+ END AS startedAt
2781
+ FROM span_events
2782
+ WHERE parentSpanId IS NULL
2783
+ )`,
2784
+ `current_roots AS (
2785
+ SELECT * EXCLUDE (rootRank)
2786
+ FROM (
2787
+ SELECT *, row_number() OVER (PARTITION BY traceId ORDER BY cursorId DESC) AS rootRank
2788
+ FROM root_events
2789
+ )
2790
+ WHERE rootRank = 1
2791
+ )`,
2792
+ `root_scope AS (
2793
+ SELECT *
2794
+ FROM current_roots r
2795
+ WHERE r.endedAt IS NOT NULL
2796
+ AND r.startedAt >= CAST(? AS TIMESTAMP)
2797
+ AND r.startedAt < CAST(? AS TIMESTAMP)
2798
+ )`
2799
+ ];
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
+ )
2812
+ WHERE currentRank = 1
2813
+ )`);
2814
+ if (relatedCollections.has("scores")) ctes.push(`current_scores AS (
2815
+ SELECT s.*
2816
+ FROM score_events s
2817
+ INNER JOIN root_scope roots ON roots.traceId = s.traceId
2818
+ )`);
2819
+ ctes.push(`candidates AS (
2820
+ SELECT ${TRACE_SELECT}
2821
+ FROM root_scope r
2822
+ WHERE ${conditions.slice(3).join("\n AND ") || "TRUE"}
2823
+ )`);
2824
+ const candidates = `WITH ${ctes.join(",\n ")}`;
2825
+ if (plan.result === "groups") {
2826
+ const pageCondition = plan.cursor ? `AND threadId > ?` : "";
2827
+ if (plan.cursor) values.push(plan.cursor.threadId);
2828
+ values.push(plan.limit + 1);
2829
+ return {
2830
+ sql: `${candidates}
2831
+ SELECT threadId
2832
+ FROM candidates
2833
+ WHERE threadId IS NOT NULL ${pageCondition}
2834
+ GROUP BY threadId
2835
+ ORDER BY threadId ASC
2836
+ LIMIT ?`,
2837
+ values
2838
+ };
2839
+ }
2840
+ const orderField = plan.orderBy.field;
2841
+ const direction = plan.orderBy.direction === "asc" ? "ASC" : "DESC";
2842
+ let pageCondition = "";
2843
+ if (plan.cursor) {
2844
+ pageCondition = `WHERE (${orderField} ${plan.orderBy.direction === "asc" ? ">" : "<"} CAST(? AS TIMESTAMP) OR (${orderField} = CAST(? AS TIMESTAMP) AND traceId > ?))`;
2845
+ values.push(plan.cursor.sortValue, plan.cursor.sortValue, plan.cursor.traceId);
2846
+ }
2847
+ values.push(plan.limit + 1);
2848
+ return {
2849
+ sql: `${candidates}
2850
+ SELECT *
2851
+ FROM candidates
2852
+ ${pageCondition}
2853
+ ORDER BY ${orderField} ${direction}, traceId ASC
2854
+ LIMIT ?`,
2855
+ values
2856
+ };
2857
+ }
2858
+ function asIsoTimestamp(value) {
2859
+ return value instanceof Date ? value.toISOString() : new Date(value).toISOString();
2860
+ }
2861
+ async function queryTraces(db, plan) {
2862
+ const query = compileDuckDBTraceQuery(plan);
2863
+ const rows = await db.query(query.sql, query.values);
2864
+ const visibleRows = rows.slice(0, plan.limit);
2865
+ if (plan.result === "groups") {
2866
+ const groups = visibleRows.map((row) => ({ threadId: String(row.threadId) }));
2867
+ const last = groups.at(-1);
2868
+ return _mastra_core_storage.traceQueryResponseSchema.parse({
2869
+ groups,
2870
+ page: { next: rows.length > plan.limit && last ? _mastra_core_storage.encodeTraceQueryCursor(plan, {
2871
+ result: "groups",
2872
+ threadId: last.threadId
2873
+ }) : null }
2874
+ });
2875
+ }
2876
+ const traces = visibleRows.map((row) => ({
2877
+ traceId: String(row.traceId),
2878
+ rootSpanId: String(row.rootSpanId),
2879
+ threadId: row.threadId == null ? null : String(row.threadId),
2880
+ resourceId: row.resourceId == null ? null : String(row.resourceId),
2881
+ startedAt: asIsoTimestamp(row.startedAt),
2882
+ endedAt: asIsoTimestamp(row.endedAt),
2883
+ entityName: row.entityName == null ? null : String(row.entityName),
2884
+ entityType: row.entityType == null ? null : String(row.entityType),
2885
+ environment: row.environment == null ? null : String(row.environment),
2886
+ status: row.status
2887
+ }));
2888
+ const last = traces.at(-1);
2889
+ return _mastra_core_storage.traceQueryResponseSchema.parse({
2890
+ traces,
2891
+ page: { next: rows.length > plan.limit && last ? _mastra_core_storage.encodeTraceQueryCursor(plan, {
2892
+ result: "traces",
2893
+ sortValue: last[plan.orderBy.field],
2894
+ traceId: last.traceId
2895
+ }) : null }
2896
+ });
2897
+ }
2898
+ //#endregion
2522
2899
  //#region src/storage/domains/observability/tracing.ts
2523
2900
  const COLUMNS_SQL = [
2524
2901
  "eventType",
@@ -3015,11 +3392,36 @@ async function batchCreateSpans(db, args) {
3015
3392
  return events;
3016
3393
  }));
3017
3394
  }
3018
- /** Delete all span events for the given trace IDs. */
3395
+ /**
3396
+ * Delete all span events for the given trace IDs, cascading to trace-linked
3397
+ * signal events (metrics, logs, scores, feedback). Signal rows with a NULL
3398
+ * traceId are never affected. When the optional tenant scope
3399
+ * (`organizationId` / `resourceId`) is set, every DELETE additionally
3400
+ * requires the row's tenant columns to match.
3401
+ */
3019
3402
  async function batchDeleteTraces(db, args) {
3020
3403
  if (args.traceIds.length === 0) return;
3021
3404
  const placeholders = args.traceIds.map(() => "?").join(", ");
3022
- await db.execute(`DELETE FROM span_events WHERE traceId IN (${placeholders})`, args.traceIds);
3405
+ const params = [...args.traceIds];
3406
+ let scopeCondition = "";
3407
+ if (args.organizationId !== void 0) {
3408
+ scopeCondition += ` AND organizationId = ?`;
3409
+ params.push(args.organizationId);
3410
+ }
3411
+ if (args.resourceId !== void 0) {
3412
+ scopeCondition += ` AND resourceId = ?`;
3413
+ params.push(args.resourceId);
3414
+ }
3415
+ await db.executeTransaction([
3416
+ "span_events",
3417
+ "metric_events",
3418
+ "log_events",
3419
+ "score_events",
3420
+ "feedback_events"
3421
+ ].map((table) => ({
3422
+ sql: `DELETE FROM ${table} WHERE traceId IN (${placeholders})${scopeCondition}`,
3423
+ params
3424
+ })));
3023
3425
  }
3024
3426
  /** Reconstruct a single span from its event history. */
3025
3427
  async function getSpan(db, args) {
@@ -3717,11 +4119,16 @@ var ObservabilityStorageDuckDB = class extends _mastra_core_storage.Observabilit
3717
4119
  };
3718
4120
  }
3719
4121
  getFeatures() {
3720
- if (!deltaPollingFeatureEnabled()) return ["metrics", "logs"];
4122
+ if (!deltaPollingFeatureEnabled()) return [
4123
+ "metrics",
4124
+ "logs",
4125
+ "trace-query"
4126
+ ];
3721
4127
  return [
3722
4128
  "metrics",
3723
4129
  "logs",
3724
- "delta-polling"
4130
+ "delta-polling",
4131
+ "trace-query"
3725
4132
  ];
3726
4133
  }
3727
4134
  async createSpan(args) {
@@ -3751,6 +4158,9 @@ var ObservabilityStorageDuckDB = class extends _mastra_core_storage.Observabilit
3751
4158
  async listTraces(args) {
3752
4159
  return listTraces(this.db, args);
3753
4160
  }
4161
+ async queryTraces(plan) {
4162
+ return queryTraces(this.db, plan);
4163
+ }
3754
4164
  async listTracesLight(args) {
3755
4165
  if (args.mode === "delta") return super.listTracesLight(args);
3756
4166
  return listTracesLight(this.db, args);
@@ -3858,4 +4268,4 @@ var ObservabilityStorageDuckDB = class extends _mastra_core_storage.Observabilit
3858
4268
  //#endregion
3859
4269
  exports.ObservabilityStorageDuckDB = ObservabilityStorageDuckDB;
3860
4270
 
3861
- //# sourceMappingURL=observability-CYOty2wB.cjs.map
4271
+ //# sourceMappingURL=observability-yLoG0tl3.cjs.map