@mastra/duckdb 1.16.0-alpha.2 → 1.17.0-alpha.0

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 (37) hide show
  1. package/dist/docs/SKILL.md +1 -1
  2. package/dist/docs/assets/SOURCE_MAP.json +1 -1
  3. package/dist/{features-DH60yLCA.cjs → features-CMkGwt1J.cjs} +70 -7
  4. package/dist/features-CMkGwt1J.cjs.map +1 -0
  5. package/dist/{features-B8gl38Ue.js → features-dc98I6Rx.js} +61 -4
  6. package/dist/features-dc98I6Rx.js.map +1 -0
  7. package/dist/index.cjs +23 -8
  8. package/dist/index.cjs.map +1 -1
  9. package/dist/index.js +23 -8
  10. package/dist/index.js.map +1 -1
  11. package/dist/{observability-BWSYzhM2.js → observability-DlRTQlrI.js} +110 -15
  12. package/dist/observability-DlRTQlrI.js.map +1 -0
  13. package/dist/{observability-B-Vnz-ZL.cjs → observability-Dr89aflR.cjs} +109 -14
  14. package/dist/observability-Dr89aflR.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/ddl.d.ts +1 -1
  18. package/dist/storage/domains/observability/ddl.d.ts.map +1 -1
  19. package/dist/storage/domains/observability/index.d.ts +1 -1
  20. package/dist/storage/domains/observability/index.d.ts.map +1 -1
  21. package/dist/storage/domains/observability/preview-compat.d.ts +1 -0
  22. package/dist/storage/domains/observability/preview-compat.d.ts.map +1 -1
  23. package/dist/storage/domains/observability/span-query.d.ts +1 -0
  24. package/dist/storage/domains/observability/span-query.d.ts.map +1 -1
  25. package/dist/storage/domains/observability/thread-query.d.ts +1 -0
  26. package/dist/storage/domains/observability/thread-query.d.ts.map +1 -1
  27. package/dist/storage/domains/observability/trace-query.d.ts.map +1 -1
  28. package/dist/storage/domains/observability/tracing.d.ts.map +1 -1
  29. package/dist/storage/features.d.ts +3 -1
  30. package/dist/storage/features.d.ts.map +1 -1
  31. package/dist/storage/index.d.ts +3 -0
  32. package/dist/storage/index.d.ts.map +1 -1
  33. package/package.json +5 -5
  34. package/dist/features-B8gl38Ue.js.map +0 -1
  35. package/dist/features-DH60yLCA.cjs.map +0 -1
  36. package/dist/observability-B-Vnz-ZL.cjs.map +0 -1
  37. package/dist/observability-BWSYzhM2.js.map +0 -1
@@ -1,7 +1,7 @@
1
- import { a as timeToFirstChunkSupported, i as timeToFirstChunkFeatures, n as spanQueryFeatures, o as DuckDBConnection, s as DuckDBQueryTimeoutError, t as spanAggregateFeatures } from "./features-B8gl38Ue.js";
1
+ import { a as timeToFirstTokenSupported, c as DuckDBQueryTimeoutError, i as timeToFirstChunkSupported, n as spanQueryFeatures, o as timingFeatures, s as DuckDBConnection, t as spanAggregateFeatures } from "./features-dc98I6Rx.js";
2
2
  import { ErrorCategory, ErrorDomain, MastraError } from "@mastra/core/error";
3
3
  import * as coreStorage from "@mastra/core/storage";
4
- import { BRANCH_SPAN_TYPES, METRIC_DISTINCT_COLUMNS, ObservabilityStorage, computeTraceStatus, createStorageErrorId, executeRetentionPrune, feedbackRecordSchema, listBranchesArgsSchema, listFeedbackArgsSchema, listLogsArgsSchema, listMetricsArgsSchema, listScoresArgsSchema, listTracesArgsSchema, resolveRetentionTargets, retentionCutoffMs, toTraceSpans } from "@mastra/core/storage";
4
+ import { BRANCH_SPAN_TYPES, METRIC_DISTINCT_COLUMNS, ObservabilityStorage, computeTraceStatus, createStorageErrorId, executeRetentionPrune, feedbackRecordSchema, getStringAttribute, listBranchesArgsSchema, listFeedbackArgsSchema, listLogsArgsSchema, listMetricsArgsSchema, listScoresArgsSchema, listTracesArgsSchema, resolveRetentionTargets, retentionCutoffMs, toTraceSpans } from "@mastra/core/storage";
5
5
  import { coreFeatures } from "@mastra/core/features";
6
6
  import { EntityType } from "@mastra/core/observability";
7
7
  import { parseFieldKey } from "@mastra/core/utils";
@@ -106,6 +106,17 @@ CREATE TABLE IF NOT EXISTS span_events (
106
106
  endedAt TIMESTAMP,
107
107
  timeToFirstChunkMs DOUBLE,
108
108
 
109
+ -- Native span fields, stored as supplied (NULL when the producer set none)
110
+ externalParentSpanId VARCHAR,
111
+ resumedFromSpanId VARCHAR,
112
+ model VARCHAR,
113
+ provider VARCHAR,
114
+ outcome VARCHAR,
115
+ stopReason VARCHAR,
116
+ timeToFirstTokenMs DOUBLE,
117
+ errorCount INTEGER,
118
+ stopReasonContext JSON,
119
+
109
120
  -- JSON fields
110
121
  attributes JSON,
111
122
  metadata JSON,
@@ -377,6 +388,15 @@ const ALL_MIGRATIONS = [
377
388
  `ALTER TABLE span_events ADD COLUMN IF NOT EXISTS hasOutputPayload BOOLEAN`,
378
389
  `ALTER TABLE span_events ADD COLUMN IF NOT EXISTS hasErrorPayload BOOLEAN`,
379
390
  `ALTER TABLE span_events ADD COLUMN IF NOT EXISTS timeToFirstChunkMs DOUBLE`,
391
+ `ALTER TABLE span_events ADD COLUMN IF NOT EXISTS externalParentSpanId VARCHAR`,
392
+ `ALTER TABLE span_events ADD COLUMN IF NOT EXISTS resumedFromSpanId VARCHAR`,
393
+ `ALTER TABLE span_events ADD COLUMN IF NOT EXISTS model VARCHAR`,
394
+ `ALTER TABLE span_events ADD COLUMN IF NOT EXISTS provider VARCHAR`,
395
+ `ALTER TABLE span_events ADD COLUMN IF NOT EXISTS outcome VARCHAR`,
396
+ `ALTER TABLE span_events ADD COLUMN IF NOT EXISTS stopReason VARCHAR`,
397
+ `ALTER TABLE span_events ADD COLUMN IF NOT EXISTS timeToFirstTokenMs DOUBLE`,
398
+ `ALTER TABLE span_events ADD COLUMN IF NOT EXISTS errorCount INTEGER`,
399
+ `ALTER TABLE span_events ADD COLUMN IF NOT EXISTS stopReasonContext JSON`,
380
400
  `ALTER TABLE span_events ADD COLUMN IF NOT EXISTS parentEntityType VARCHAR`,
381
401
  `ALTER TABLE span_events ADD COLUMN IF NOT EXISTS parentEntityId VARCHAR`,
382
402
  `ALTER TABLE span_events ADD COLUMN IF NOT EXISTS parentEntityName VARCHAR`,
@@ -2879,6 +2899,10 @@ const TRACE_FIELDS = {
2879
2899
  sql: "r.timeToFirstChunkMs",
2880
2900
  parameterType: "scalar"
2881
2901
  },
2902
+ timeToFirstTokenMs: {
2903
+ sql: "r.timeToFirstTokenMs",
2904
+ parameterType: "scalar"
2905
+ },
2882
2906
  entityId: {
2883
2907
  sql: "r.entityId",
2884
2908
  parameterType: "scalar"
@@ -2945,6 +2969,10 @@ const SPAN_FIELDS = {
2945
2969
  sql: "s.timeToFirstChunkMs",
2946
2970
  parameterType: "scalar"
2947
2971
  },
2972
+ timeToFirstTokenMs: {
2973
+ sql: "s.timeToFirstTokenMs",
2974
+ parameterType: "scalar"
2975
+ },
2948
2976
  status: {
2949
2977
  sql: "s.status",
2950
2978
  parameterType: "scalar"
@@ -3155,6 +3183,7 @@ const TRACE_SELECT = `
3155
3183
  r.startedAt AS startedAt,
3156
3184
  r.endedAt AS endedAt,
3157
3185
  r.timeToFirstChunkMs AS timeToFirstChunkMs,
3186
+ r.timeToFirstTokenMs AS timeToFirstTokenMs,
3158
3187
  r.entityName AS entityName,
3159
3188
  r.entityType AS entityType,
3160
3189
  r.environment AS environment,
@@ -3391,6 +3420,7 @@ const ROOT_PUSHDOWN_FIELDS = /* @__PURE__ */ new Set([
3391
3420
  "organizationId",
3392
3421
  "endedAt",
3393
3422
  "timeToFirstChunkMs",
3423
+ "timeToFirstTokenMs",
3394
3424
  "entityId",
3395
3425
  "entityName",
3396
3426
  "entityType",
@@ -3522,6 +3552,7 @@ function compileDuckDBTraceScope(relatedCollections, scope, timeRange, rootPredi
3522
3552
  endedAt,
3523
3553
  ${durationMsSql("startedAt", "endedAt")} AS durationMs,
3524
3554
  timeToFirstChunkMs,
3555
+ timeToFirstTokenMs,
3525
3556
  CASE WHEN error IS NOT NULL THEN 'error' ELSE 'success' END AS status,
3526
3557
  error,
3527
3558
  entityType,
@@ -3862,7 +3893,8 @@ function traceFromRow(row) {
3862
3893
  entityType: row.entityType == null ? null : String(row.entityType),
3863
3894
  environment: row.environment == null ? null : String(row.environment),
3864
3895
  status: row.status,
3865
- ...timeToFirstChunkSupported && { timeToFirstChunkMs: row.timeToFirstChunkMs == null ? null : Number(row.timeToFirstChunkMs) }
3896
+ ...timeToFirstChunkSupported && { timeToFirstChunkMs: row.timeToFirstChunkMs == null ? null : Number(row.timeToFirstChunkMs) },
3897
+ ...timeToFirstTokenSupported && { timeToFirstTokenMs: row.timeToFirstTokenMs == null ? null : Number(row.timeToFirstTokenMs) }
3866
3898
  };
3867
3899
  }
3868
3900
  async function queryTraces(db, plan) {
@@ -3983,7 +4015,8 @@ const fields = [
3983
4015
  "experimentId",
3984
4016
  "environment",
3985
4017
  "executionSource",
3986
- "timeToFirstChunkMs"
4018
+ "timeToFirstChunkMs",
4019
+ "timeToFirstTokenMs"
3987
4020
  ];
3988
4021
  function keys(rows, values, alias = "") {
3989
4022
  return rows.map((row) => `(${identityFields.map((field) => {
@@ -4110,11 +4143,12 @@ async function querySpans(db, plan) {
4110
4143
  };
4111
4144
  const compiled = compileDuckDBSpanQuery(plan);
4112
4145
  const rows = await query(compiled.sql, compiled.values);
4113
- const selected = rows.map(({ cursorId: _cursorId, startedAt, endedAt, timeToFirstChunkMs, ...row }) => ({
4146
+ const selected = rows.map(({ cursorId: _cursorId, startedAt, endedAt, timeToFirstChunkMs, timeToFirstTokenMs, ...row }) => ({
4114
4147
  ...row,
4115
4148
  startedAt: startedAt.toISOString(),
4116
4149
  endedAt: endedAt.toISOString(),
4117
- ...timeToFirstChunkSupported && { timeToFirstChunkMs: timeToFirstChunkMs == null ? null : Number(timeToFirstChunkMs) }
4150
+ ...timeToFirstChunkSupported && { timeToFirstChunkMs: timeToFirstChunkMs == null ? null : Number(timeToFirstChunkMs) },
4151
+ ...timeToFirstTokenSupported && { timeToFirstTokenMs: timeToFirstTokenMs == null ? null : Number(timeToFirstTokenMs) }
4118
4152
  }));
4119
4153
  const page = rows.slice(0, plan.limit);
4120
4154
  if (!page.length) return buildSpanQueryResponse(plan, [], []);
@@ -4258,8 +4292,12 @@ function compileDuckDBThreadRowsQuery(plan, strategy = "full") {
4258
4292
  }
4259
4293
  values.push(plan.limit + 1);
4260
4294
  const filtered = predicateFields(plan.where);
4261
- const firstContext = [...contextFields, "timeToFirstChunkMs"].filter((field) => field === "resourceId" || filtered.has(field));
4262
- const contextExpression = (field) => field === "executionSource" ? "source AS executionSource" : field === "timeToFirstChunkMs" ? "CASE WHEN spanType = 'agent_run' THEN timeToFirstChunkMs END AS timeToFirstChunkMs" : field;
4295
+ const firstContext = [
4296
+ ...contextFields,
4297
+ "timeToFirstChunkMs",
4298
+ "timeToFirstTokenMs"
4299
+ ].filter((field) => field === "resourceId" || filtered.has(field));
4300
+ const contextExpression = (field) => field === "executionSource" ? "source AS executionSource" : field === "timeToFirstChunkMs" || field === "timeToFirstTokenMs" ? `CASE WHEN spanType = 'agent_run' THEN ${field} END AS ${field}` : field;
4263
4301
  const lastFields = [
4264
4302
  "traceId",
4265
4303
  "spanId",
@@ -4345,6 +4383,7 @@ async function queryThreadRows(db, plan, strategy = "auto") {
4345
4383
  const payloads = await run(`SELECT organizationId, traceId, cursorId,
4346
4384
  ${contextFields.map((field) => field === "executionSource" ? "source AS executionSource" : field).join(", ")},
4347
4385
  CASE WHEN spanType = 'agent_run' THEN timeToFirstChunkMs END AS timeToFirstChunkMs,
4386
+ CASE WHEN spanType = 'agent_run' THEN timeToFirstTokenMs END AS timeToFirstTokenMs,
4348
4387
  CASE WHEN error IS NULL THEN 'success' ELSE 'error' END AS status,
4349
4388
  ${[
4350
4389
  "input",
@@ -4373,6 +4412,7 @@ async function queryThreadRows(db, plan, strategy = "auto") {
4373
4412
  endedAt: row.endedAt.toISOString(),
4374
4413
  traceCount: Number(row.traceCount),
4375
4414
  timeToFirstChunkMs: first.timeToFirstChunkMs,
4415
+ ...timeToFirstTokenSupported && { timeToFirstTokenMs: first.timeToFirstTokenMs },
4376
4416
  inputPreview: readPreview(first.inputPreview, first.input, true),
4377
4417
  outputPreview: readPreview(last.outputPreview, last.output, true),
4378
4418
  errorPreview: readPreview(last.errorPreview, last.error, true)
@@ -4782,6 +4822,15 @@ const COLUMNS_SQL = [
4782
4822
  "isEvent",
4783
4823
  "endedAt",
4784
4824
  "timeToFirstChunkMs",
4825
+ "externalParentSpanId",
4826
+ "resumedFromSpanId",
4827
+ "model",
4828
+ "provider",
4829
+ "outcome",
4830
+ "stopReason",
4831
+ "timeToFirstTokenMs",
4832
+ "errorCount",
4833
+ "stopReasonContext",
4785
4834
  "experimentId",
4786
4835
  "entityType",
4787
4836
  "entityId",
@@ -4897,7 +4946,16 @@ const SPAN_RECONSTRUCT_SELECT = `
4897
4946
  ${argMaxNonNull("input")},
4898
4947
  ${argMaxNonNull("output")},
4899
4948
  ${argMaxNonNull("error")},
4900
- ${argMaxNonNull("requestContext")}
4949
+ ${argMaxNonNull("requestContext")},
4950
+ ${argMaxNonNull("externalParentSpanId")},
4951
+ ${argMaxNonNull("resumedFromSpanId")},
4952
+ ${argMaxNonNull("model")},
4953
+ ${argMaxNonNull("provider")},
4954
+ ${argMaxNonNull("outcome")},
4955
+ ${argMaxNonNull("stopReason")},
4956
+ ${argMaxNonNull("timeToFirstTokenMs")},
4957
+ ${argMaxNonNull("errorCount")},
4958
+ ${argMaxNonNull("stopReasonContext")}
4901
4959
  FROM span_events
4902
4960
  `;
4903
4961
  /** Lightweight variant — only timeline-relevant columns. */
@@ -5093,6 +5151,7 @@ function rowToLightSpanRecordWithPreview(row) {
5093
5151
  };
5094
5152
  }
5095
5153
  function rowToSpanRecord(row) {
5154
+ const attributes = parseJson(row.attributes);
5096
5155
  return {
5097
5156
  traceId: row.traceId,
5098
5157
  spanId: row.spanId,
@@ -5102,6 +5161,15 @@ function rowToSpanRecord(row) {
5102
5161
  isEvent: row.isEvent,
5103
5162
  startedAt: toDate(row.startedAt),
5104
5163
  endedAt: rowEndedAt(row),
5164
+ externalParentSpanId: row.externalParentSpanId ?? null,
5165
+ resumedFromSpanId: row.resumedFromSpanId ?? null,
5166
+ model: row.model ?? getStringAttribute(attributes, "model"),
5167
+ provider: row.provider ?? getStringAttribute(attributes, "provider"),
5168
+ outcome: row.outcome ?? null,
5169
+ stopReason: row.stopReason ?? null,
5170
+ timeToFirstTokenMs: row.timeToFirstTokenMs ?? null,
5171
+ errorCount: row.errorCount ?? null,
5172
+ stopReasonContext: parseJson(row.stopReasonContext),
5105
5173
  experimentId: row.experimentId ?? null,
5106
5174
  entityType: row.entityType ?? null,
5107
5175
  entityId: row.entityId ?? null,
@@ -5125,7 +5193,7 @@ function rowToSpanRecord(row) {
5125
5193
  environment: row.environment ?? null,
5126
5194
  source: row.source ?? null,
5127
5195
  serviceName: row.serviceName ?? null,
5128
- attributes: parseJson(row.attributes),
5196
+ attributes,
5129
5197
  metadata: parseJson(row.metadata),
5130
5198
  tags: parseJsonArray(row.tags),
5131
5199
  scope: parseJson(row.scope),
@@ -5288,6 +5356,15 @@ function toValuesTuple(row) {
5288
5356
  v(row.isEvent),
5289
5357
  v(row.endedAt),
5290
5358
  v(row.timeToFirstChunkMs),
5359
+ v(row.externalParentSpanId),
5360
+ v(row.resumedFromSpanId),
5361
+ v(row.model),
5362
+ v(row.provider),
5363
+ v(row.outcome),
5364
+ v(row.stopReason),
5365
+ v(row.timeToFirstTokenMs),
5366
+ v(row.errorCount),
5367
+ jsonV(row.stopReasonContext),
5291
5368
  v(row.experimentId),
5292
5369
  v(row.entityType),
5293
5370
  v(row.entityId),
@@ -5333,6 +5410,24 @@ async function insertSpanEvents(db, rows) {
5333
5410
  const tuples = rows.map((row) => `(${toValuesTuple(row)})`).join(",\n");
5334
5411
  await db.execute(`INSERT INTO span_events (${COLUMNS_SQL}) VALUES ${tuples}`);
5335
5412
  }
5413
+ /**
5414
+ * Columns copied as supplied onto both event rows (NULL when unset). Previews
5415
+ * stay out: the start row derives them from the payload it keeps.
5416
+ */
5417
+ function copiedSpanColumns(s) {
5418
+ return {
5419
+ timeToFirstChunkMs: s.timeToFirstChunkMs ?? null,
5420
+ externalParentSpanId: s.externalParentSpanId ?? null,
5421
+ resumedFromSpanId: s.resumedFromSpanId ?? null,
5422
+ model: s.model ?? null,
5423
+ provider: s.provider ?? null,
5424
+ outcome: s.outcome ?? null,
5425
+ stopReason: s.stopReason ?? null,
5426
+ timeToFirstTokenMs: s.timeToFirstTokenMs ?? null,
5427
+ errorCount: s.errorCount ?? null,
5428
+ stopReasonContext: s.stopReasonContext ?? null
5429
+ };
5430
+ }
5336
5431
  function createStartSpanRow(s) {
5337
5432
  const payloadOnEndRow = !!s.endedAt && !s.isEvent;
5338
5433
  const input = previewOf(!payloadOnEndRow, s.input, s.inputPreview);
@@ -5346,7 +5441,7 @@ function createStartSpanRow(s) {
5346
5441
  spanType: s.spanType,
5347
5442
  isEvent: s.isEvent,
5348
5443
  endedAt: s.isEvent ? s.startedAt : null,
5349
- timeToFirstChunkMs: s.timeToFirstChunkMs ?? null,
5444
+ ...copiedSpanColumns(s),
5350
5445
  experimentId: s.experimentId ?? null,
5351
5446
  entityType: s.entityType ?? null,
5352
5447
  entityId: s.entityId ?? null,
@@ -5401,7 +5496,7 @@ function createEndSpanRow(s) {
5401
5496
  spanType: s.spanType,
5402
5497
  isEvent: s.isEvent,
5403
5498
  endedAt: s.endedAt ?? null,
5404
- timeToFirstChunkMs: s.timeToFirstChunkMs ?? null,
5499
+ ...copiedSpanColumns(s),
5405
5500
  experimentId: s.experimentId ?? null,
5406
5501
  entityType: s.entityType ?? null,
5407
5502
  entityId: s.entityId ?? null,
@@ -6265,7 +6360,7 @@ var ObservabilityStorageDuckDB = class ObservabilityStorageDuckDB extends Observ
6265
6360
  "trace-query-tenant-scope",
6266
6361
  "feedback",
6267
6362
  "trace-query-context-ids",
6268
- ...timeToFirstChunkFeatures,
6363
+ ...timingFeatures,
6269
6364
  "trace-query-root-span-fields",
6270
6365
  "trace-query-root-entity-id"
6271
6366
  ];
@@ -6290,7 +6385,7 @@ var ObservabilityStorageDuckDB = class ObservabilityStorageDuckDB extends Observ
6290
6385
  "trace-query-tenant-scope",
6291
6386
  "feedback",
6292
6387
  "trace-query-context-ids",
6293
- ...timeToFirstChunkFeatures,
6388
+ ...timingFeatures,
6294
6389
  "trace-query-root-span-fields",
6295
6390
  "trace-query-root-entity-id"
6296
6391
  ];
@@ -6456,4 +6551,4 @@ var ObservabilityStorageDuckDB = class ObservabilityStorageDuckDB extends Observ
6456
6551
  };
6457
6552
  export { ObservabilityStorageDuckDB };
6458
6553
 
6459
- //# sourceMappingURL=observability-BWSYzhM2.js.map
6554
+ //# sourceMappingURL=observability-DlRTQlrI.js.map