@mastra/clickhouse 1.28.0-alpha.1 → 1.28.0-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.
package/dist/index.js CHANGED
@@ -6916,6 +6916,13 @@ const timingFeatures = [
6916
6916
  ...timeToFirstTokenSupported ? ["trace-query-time-to-first-token"] : [],
6917
6917
  ...timeToFirstTokenSupported && timeToFirstTokenSortSupported ? ["trace-query-time-to-first-token-sort"] : []
6918
6918
  ];
6919
+ /**
6920
+ * Outcome fields follow the same rule: core before them rejects their predicates and strict rows,
6921
+ * so they are only returned and declared when core knows them.
6922
+ */
6923
+ const spanQueryOutcomeFieldsSupported = "outcome" in (coreStorage.SPAN_QUERY_FIELD_REGISTRY ?? {});
6924
+ const traceQueryOutcomeFieldsSupported = "outcome" in (coreStorage.TRACE_QUERY_FIELD_REGISTRY?.trace ?? {});
6925
+ const outcomeFeatures = [...spanQueryOutcomeFieldsSupported ? ["span-query-outcome-fields"] : [], ...traceQueryOutcomeFieldsSupported ? ["trace-query-outcome-fields"] : []];
6919
6926
  /** Order fields holding numbers that can be empty; the rest are timestamps. */
6920
6927
  const NUMERIC_ORDER_FIELDS = /* @__PURE__ */ new Set(["timeToFirstChunkMs", "timeToFirstTokenMs"]);
6921
6928
  function durationMsSql(startedAt, endedAt) {
@@ -7002,6 +7009,14 @@ const TRACE_FIELDS = {
7002
7009
  sql: TRACE_STATUS_SQL,
7003
7010
  parameterType: "String"
7004
7011
  },
7012
+ outcome: {
7013
+ sql: "r.outcome",
7014
+ parameterType: "String"
7015
+ },
7016
+ stopReason: {
7017
+ sql: "r.stopReason",
7018
+ parameterType: "String"
7019
+ },
7005
7020
  tags: {
7006
7021
  sql: "r.tags",
7007
7022
  parameterType: "String"
@@ -7048,6 +7063,14 @@ const SPAN_FIELDS = {
7048
7063
  sql: "s.status",
7049
7064
  parameterType: "String"
7050
7065
  },
7066
+ outcome: {
7067
+ sql: "s.outcome",
7068
+ parameterType: "String"
7069
+ },
7070
+ stopReason: {
7071
+ sql: "s.stopReason",
7072
+ parameterType: "String"
7073
+ },
7051
7074
  error: {
7052
7075
  sql: "s.error",
7053
7076
  parameterType: "String"
@@ -7257,6 +7280,9 @@ const TRACE_SELECT = `
7257
7280
  r.environment AS environment,
7258
7281
  r.timeToFirstChunkMs AS timeToFirstChunkMs,
7259
7282
  r.timeToFirstTokenMs AS timeToFirstTokenMs,
7283
+ r.outcome AS outcome,
7284
+ r.stopReason AS stopReason,
7285
+ r.stopReasonContext AS stopReasonContext,
7260
7286
  ${TRACE_STATUS_SQL} AS status`;
7261
7287
  var ParameterBuilder = class {
7262
7288
  params = {};
@@ -7457,14 +7483,16 @@ function compileClickHouseTraceScope(selection, relationCollections, parameters,
7457
7483
  traceId,
7458
7484
  name,
7459
7485
  spanType,
7460
- if(JSONType(attributes, 'model') = 'String', JSONExtractString(attributes, 'model'), NULL) AS model,
7461
- if(JSONType(attributes, 'provider') = 'String', JSONExtractString(attributes, 'provider'), NULL) AS provider,
7486
+ coalesce(model, if(JSONType(attributes, 'model') = 'String', JSONExtractString(attributes, 'model'), NULL)) AS model,
7487
+ coalesce(provider, if(JSONType(attributes, 'provider') = 'String', JSONExtractString(attributes, 'provider'), NULL)) AS provider,
7462
7488
  startedAt,
7463
7489
  endedAt,
7464
7490
  ${durationMsSql("startedAt", "endedAt")} AS durationMs,
7465
7491
  timeToFirstChunkMs,
7466
7492
  timeToFirstTokenMs,
7467
7493
  if(isNotNull(error), 'error', 'success') AS status,
7494
+ outcome,
7495
+ stopReason,
7468
7496
  error,
7469
7497
  entityType,
7470
7498
  entityId,
@@ -7568,7 +7596,7 @@ const QUERY_TRACES_SCOPE = {
7568
7596
  oneRootPerTrace: true,
7569
7597
  spanExistence: true
7570
7598
  };
7571
- const TRACE_LIST_SELECT = TRACE_SELECT.split("\n").filter((line) => !/ AS (metadata|inputPreview|outputPreview|errorPreview),$/.test(line)).join("\n");
7599
+ const TRACE_LIST_SELECT = TRACE_SELECT.split("\n").filter((line) => !/ AS (metadata|inputPreview|outputPreview|errorPreview|stopReasonContext),$/.test(line)).join("\n");
7572
7600
  function traceOrder(plan) {
7573
7601
  return {
7574
7602
  field: resolveOrderField(plan.orderBy.field),
@@ -7728,7 +7756,7 @@ function compileClickHouseTraceRootPayloads(keys, scope, columns = "payload") {
7728
7756
  const tenant = (value) => `${parameters.add(value ?? "", "String")}, ${value === null ? 1 : 0}`;
7729
7757
  const tuples = keys.map((key) => `(${parameters.add(key.startedAt, "DateTime64(3, 'UTC')")}, ${parameters.add(key.traceId, "String")}, ${parameters.add(key.dedupeKey, "String")}, ${parameters.add(key.endedAt, "DateTime64(3, 'UTC')")}, ${tenant(key.organizationId)}, ${tenant(key.resourceId)})`);
7730
7758
  return {
7731
- query: `SELECT traceId, spanId AS rootSpanId, dedupeKey, organizationId, resourceId, ${columns === "payload" ? `metadataRaw AS metadata, ${PREVIEW_COLUMNS.join(", ")}` : "input, output, error"}
7759
+ query: `SELECT traceId, spanId AS rootSpanId, dedupeKey, organizationId, resourceId, ${columns === "payload" ? `metadataRaw AS metadata, stopReasonContext, ${PREVIEW_COLUMNS.join(", ")}` : "input, output, error"}
7732
7760
  FROM ${TABLE_TRACE_ROOTS}
7733
7761
  WHERE (startedAt, traceId, dedupeKey, endedAt, ifNull(organizationId, ''), isNull(organizationId), ifNull(resourceId, ''), isNull(resourceId)) IN (${tuples.join(", ")})${compileTenantScope(scope, parameters)}
7734
7762
  ORDER BY ${ROOT_VERSION_ORDER}
@@ -7995,7 +8023,12 @@ async function queryTraces(client, plan, timeoutMs, strategy = null) {
7995
8023
  environment: row.environment == null ? null : String(row.environment),
7996
8024
  status: row.status,
7997
8025
  ...timeToFirstChunkSupported && { timeToFirstChunkMs: row.timeToFirstChunkMs == null ? null : Number(row.timeToFirstChunkMs) },
7998
- ...timeToFirstTokenSupported && { timeToFirstTokenMs: row.timeToFirstTokenMs == null ? null : Number(row.timeToFirstTokenMs) }
8026
+ ...timeToFirstTokenSupported && { timeToFirstTokenMs: row.timeToFirstTokenMs == null ? null : Number(row.timeToFirstTokenMs) },
8027
+ ...traceQueryOutcomeFieldsSupported && {
8028
+ outcome: row.outcome == null ? null : String(row.outcome),
8029
+ stopReason: row.stopReason == null ? null : String(row.stopReason),
8030
+ stopReasonContext: parseJson(row.stopReasonContext) ?? null
8031
+ }
7999
8032
  });
8000
8033
  if (plan.paginationMode === "delta") {
8001
8034
  const rows = await run(compileClickHouseTraceQuery(plan, deltaHead));
@@ -8122,7 +8155,10 @@ const displayFields = [
8122
8155
  "durationMs",
8123
8156
  "timeToFirstChunkMs",
8124
8157
  "timeToFirstTokenMs",
8125
- "status"
8158
+ "status",
8159
+ "outcome",
8160
+ "stopReason",
8161
+ "stopReasonContext"
8126
8162
  ];
8127
8163
  var Parameters = class {
8128
8164
  values = {};
@@ -8174,13 +8210,18 @@ function predicateFields$1(predicate, fields = /* @__PURE__ */ new Set()) {
8174
8210
  else fields.add(predicate.field);
8175
8211
  return fields;
8176
8212
  }
8213
+ /** Selection and filter expressions read only columns; `model`/`provider` read their dedicated columns. */
8177
8214
  function fieldExpression(field) {
8178
- if (field === "model" || field === "provider") return `if(JSONType(e.attributes, '${field}') = 'String', JSONExtractString(e.attributes, '${field}'), NULL)`;
8179
8215
  if (field === "durationMs") return "dateDiff('millisecond', e.startedAt, e.endedAt)";
8180
8216
  if (field === "status") return "if(isNull(e.error), 'success', 'error')";
8181
8217
  if (field === "error") return "if(isNull(e.error), NULL, 'error')";
8182
8218
  return `e.${field}`;
8183
8219
  }
8220
+ /** Returned values fall back to span attributes for rows written before the dedicated columns existed. */
8221
+ function displayExpression(field) {
8222
+ if (field === "model" || field === "provider") return `coalesce(e.${field}, if(JSONType(e.attributes, '${field}') = 'String', JSONExtractString(e.attributes, '${field}'), NULL))`;
8223
+ return fieldExpression(field);
8224
+ }
8184
8225
  function compileClickHouseSpanQuery(plan) {
8185
8226
  const parameters = new Parameters();
8186
8227
  const from = parameters.add(plan.timeRange.from, "DateTime64(3, 'UTC')");
@@ -8267,7 +8308,11 @@ const TRACE_BRANCHES_SPAN_FIELD_COLUMNS = {
8267
8308
  "rootEntityType",
8268
8309
  "rootEntityId",
8269
8310
  "rootEntityName",
8270
- "rootEntityVersionId"
8311
+ "rootEntityVersionId",
8312
+ "model",
8313
+ "provider",
8314
+ "outcome",
8315
+ "stopReason"
8271
8316
  ].map((field) => [field, sameColumn(field)])),
8272
8317
  status: ["error"],
8273
8318
  error: ["error"],
@@ -8380,7 +8425,7 @@ async function querySpans(client, plan, timeoutMs) {
8380
8425
  const pageParameter = (rows) => rows.map((row) => new TupleParam([...identityValues(row), row.endedAt.replace("T", " ").replace(/Z$/, "")]));
8381
8426
  const rowsWithPreviews = await run({
8382
8427
  query: `SELECT ${identities}, ${[...displayFields, ...PREVIEW_COLUMNS].map((field, index) => `data.${index + 1} AS ${field}`).join(", ")}
8383
- FROM (SELECT ${identities}, any(tuple(${[...displayFields.map(fieldExpression), ...PREVIEW_COLUMNS].join(", ")})) AS data
8428
+ FROM (SELECT ${identities}, any(tuple(${[...displayFields.map(displayExpression), ...PREVIEW_COLUMNS].join(", ")})) AS data
8384
8429
  FROM ${TABLE_SPAN_EVENTS} e WHERE ${payloadWhere} GROUP BY ${identities})`,
8385
8430
  query_params: { page: pageParameter(page) }
8386
8431
  });
@@ -8407,13 +8452,18 @@ async function querySpans(client, plan, timeoutMs) {
8407
8452
  const hydrated = page.flatMap((identity) => {
8408
8453
  const row = byIdentity.get(coreStorage.spanQueryIdentityKey(identity));
8409
8454
  if (!row) return [];
8410
- const { inputPreview: _input, outputPreview: _output, errorPreview: _error, timeToFirstChunkMs, timeToFirstTokenMs, ...metadata } = row;
8455
+ const { inputPreview: _input, outputPreview: _output, errorPreview: _error, timeToFirstChunkMs, timeToFirstTokenMs, outcome, stopReason, stopReasonContext, ...metadata } = row;
8411
8456
  return [{
8412
8457
  ...metadata,
8413
8458
  ...identity,
8414
8459
  durationMs: Number(row.durationMs),
8415
8460
  ...timeToFirstChunkSupported && { timeToFirstChunkMs: timeToFirstChunkMs == null ? null : Number(timeToFirstChunkMs) },
8416
- ...timeToFirstTokenSupported && { timeToFirstTokenMs: timeToFirstTokenMs == null ? null : Number(timeToFirstTokenMs) }
8461
+ ...timeToFirstTokenSupported && { timeToFirstTokenMs: timeToFirstTokenMs == null ? null : Number(timeToFirstTokenMs) },
8462
+ ...spanQueryOutcomeFieldsSupported && {
8463
+ outcome: outcome ?? null,
8464
+ stopReason: stopReason ?? null,
8465
+ stopReasonContext: parseJson(stopReasonContext) ?? null
8466
+ }
8417
8467
  }];
8418
8468
  });
8419
8469
  let metrics = [];
@@ -8728,6 +8778,8 @@ const DIMENSION_SQL = {
8728
8778
  entityId: "r.entityId",
8729
8779
  environment: "r.environment",
8730
8780
  status: TRACE_STATUS_SQL,
8781
+ outcome: "r.outcome",
8782
+ stopReason: "r.stopReason",
8731
8783
  serviceName: "r.serviceName",
8732
8784
  executionSource: "r.executionSource",
8733
8785
  threadId: "r.threadId",
@@ -8750,6 +8802,8 @@ const SPAN_DIMENSION_SQL = Object.fromEntries([
8750
8802
  "rootEntityName",
8751
8803
  "environment",
8752
8804
  "status",
8805
+ "outcome",
8806
+ "stopReason",
8753
8807
  "serviceName",
8754
8808
  "executionSource",
8755
8809
  "threadId",
@@ -8757,7 +8811,9 @@ const SPAN_DIMENSION_SQL = Object.fromEntries([
8757
8811
  "userId",
8758
8812
  "sessionId",
8759
8813
  "organizationId",
8760
- "experimentId"
8814
+ "experimentId",
8815
+ "model",
8816
+ "provider"
8761
8817
  ].map((field) => [field, `r.${field}`]));
8762
8818
  const PERCENTILES = {
8763
8819
  "duration.p50": .5,
@@ -9919,8 +9975,12 @@ function buildBranchCursor(row) {
9919
9975
  return row.cursorId ?? "0";
9920
9976
  }
9921
9977
  // src/storage/domains/observability/v-next/index.ts
9922
- const spanQueryFeatures = typeof coreStorage.planSpanQuery === "function" ? ["span-query", "span-query-context-fields"] : [];
9923
- const spanAggregateFeatures = typeof coreStorage.planSpanAggregate === "function" ? ["span-aggregate"] : [];
9978
+ const spanQueryFeatures = typeof coreStorage.planSpanQuery === "function" ? [
9979
+ "span-query",
9980
+ "span-query-context-fields",
9981
+ ..."model" in (coreStorage.SPAN_QUERY_FIELD_REGISTRY ?? {}) ? ["span-query-model-fields"] : []
9982
+ ] : [];
9983
+ const spanAggregateFeatures = typeof coreStorage.planSpanAggregate === "function" ? ["span-aggregate", ..."model" in (coreStorage.SPAN_AGGREGATE_DIMENSION_REGISTRY ?? {}) ? ["span-aggregate-model-dimensions"] : []] : [];
9924
9984
  const threadQueryFeatures = typeof coreStorage.planThreadRowsQuery === "function" ? ["thread-query-rows"] : [];
9925
9985
  function buildSignalMigrationRequiredMessage(args) {
9926
9986
  const tableList = args.tables.map((table) => ` - ${table.table} (${table.engine})`).join("\n");
@@ -10360,6 +10420,7 @@ var ObservabilityStorageClickhouseVNext = class extends ObservabilityStorage {
10360
10420
  "feedback",
10361
10421
  "trace-query-context-ids",
10362
10422
  ...timingFeatures,
10423
+ ...outcomeFeatures,
10363
10424
  "trace-query-root-span-fields",
10364
10425
  "trace-query-root-entity-id",
10365
10426
  "trace-aggregate",
@@ -10385,6 +10446,7 @@ var ObservabilityStorageClickhouseVNext = class extends ObservabilityStorage {
10385
10446
  "feedback",
10386
10447
  "trace-query-context-ids",
10387
10448
  ...timingFeatures,
10449
+ ...outcomeFeatures,
10388
10450
  "trace-query-root-span-fields",
10389
10451
  "trace-query-root-entity-id",
10390
10452
  "trace-aggregate",