@mastra/clickhouse 1.14.0 → 1.15.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,47 @@
1
1
  # @mastra/clickhouse
2
2
 
3
+ ## 1.15.0-alpha.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Fixed resource-scoped message includes across storage adapters so included context cannot cross resource boundaries. ([#20984](https://github.com/mastra-ai/mastra/pull/20984))
8
+
9
+ - Updated dependencies [[`6445eba`](https://github.com/mastra-ai/mastra/commit/6445eba6020abac681aba1cc9289f446cb400cbe), [`df31eb0`](https://github.com/mastra-ai/mastra/commit/df31eb0c7087d782a0d9346e467f9a4af4b0eef6), [`fcd0667`](https://github.com/mastra-ai/mastra/commit/fcd0667a4e378be35c9a1b1eb19cce78fbfd7282), [`bab06b1`](https://github.com/mastra-ai/mastra/commit/bab06b18923873a584bdfc71a6b4ec7fb4727fb7)]:
10
+ - @mastra/core@1.58.0-alpha.5
11
+
12
+ ## 1.15.0-alpha.0
13
+
14
+ ### Minor Changes
15
+
16
+ - Memory list reads now surface database errors instead of silently returning empty results. ([#17910](https://github.com/mastra-ai/mastra/pull/17910))
17
+
18
+ Previously, the paginated memory reads (`listThreads`, `listMessages`, `listMessagesByResourceId`, and `listMessagesById`) caught backend failures, logged them, and returned an empty payload like `{ threads: [], total: 0, hasMore: false }`. A transient outage (locked table, dropped connection) was therefore indistinguishable from a genuinely empty result, so an agent reading conversation history during a brief failure would treat it as "no history" and could overwrite real state. These methods now re-throw the failure as a `MastraError`. Validation (USER) errors and genuinely empty results are unchanged.
19
+
20
+ **Behavior change**
21
+
22
+ Callers that previously received an empty result on a backend failure will now receive a thrown `MastraError`. If you call these read methods directly (rather than through an agent, which already surfaces errors), wrap them so a transient outage doesn't crash the caller:
23
+
24
+ ```ts
25
+ try {
26
+ const { threads } = await storage.listThreads({ resourceId });
27
+ // ...use threads
28
+ } catch (error) {
29
+ // a real backend failure. Decide whether to retry, surface, or degrade.
30
+ // An empty thread list no longer hides here; it only means "no threads".
31
+ }
32
+ ```
33
+
34
+ ### Patch Changes
35
+
36
+ - Fixed the ClickHouse lightweight trace list: responses no longer carry the `input`, `output` and `attributes` payload blobs, and delta polling now works. ([#20677](https://github.com/mastra-ai/mastra/pull/20677))
37
+
38
+ `listTracesLight` rows now carry a short `inputPreview` in place of the full input, plus the span `metadata` and a computed `status`, so Studio's configurable trace columns keep working — in both page and delta mode. Response payloads stay small as prompts grow. There is no schema change and no migration.
39
+
40
+ Requires `@mastra/core` >= 1.57.0, which ships the shared `buildInputPreview` and `computeTraceStatus` helpers this store now imports (peer dependency bumped accordingly).
41
+
42
+ - Updated dependencies [[`e7109ee`](https://github.com/mastra-ai/mastra/commit/e7109ee6f731bacc79c885906f3c7dca8d8f013a), [`772c0c8`](https://github.com/mastra-ai/mastra/commit/772c0c897cec383258de2e6178147f8014767c7b), [`578bf2e`](https://github.com/mastra-ai/mastra/commit/578bf2e6a88e9d5b8bf502204e15a95dfbb679ae), [`06b2d87`](https://github.com/mastra-ai/mastra/commit/06b2d87e63bcdd0ed59215c6789692b9b12de376), [`ac01d63`](https://github.com/mastra-ai/mastra/commit/ac01d6355974aec73fdb8781449ed12bac582094), [`a810a05`](https://github.com/mastra-ai/mastra/commit/a810a058f62ad407cfc1701e0be36ae91145d7cf), [`f8da216`](https://github.com/mastra-ai/mastra/commit/f8da21633e7eb0e31c9ce0fc30567870d19416d3), [`6104347`](https://github.com/mastra-ai/mastra/commit/61043473ba6bfd0a25156824e853e13165562e6c), [`45bfb88`](https://github.com/mastra-ai/mastra/commit/45bfb88fd52f1dd3be20e2a38905777c96499c90), [`e3b9307`](https://github.com/mastra-ai/mastra/commit/e3b9307098daefbfae2a52ae2ef51bc9fc701190), [`d6834c5`](https://github.com/mastra-ai/mastra/commit/d6834c5a7866b16734d23900163c2414ed70d791), [`c52d346`](https://github.com/mastra-ai/mastra/commit/c52d3462ec831a5d95926ecd3d3373f5928ad2e5), [`0023e79`](https://github.com/mastra-ai/mastra/commit/0023e7919431078280abd11c89d1edeae35fcc69), [`c2ad51e`](https://github.com/mastra-ai/mastra/commit/c2ad51e2467f901eecba8c9f4a45e22a50bd7c18), [`3dc97ea`](https://github.com/mastra-ai/mastra/commit/3dc97ea415fad353b48a13095fad1835933cc12a), [`3d01cd3`](https://github.com/mastra-ai/mastra/commit/3d01cd387321b6f9c5cac31d487c84bf51b19c78), [`7bf3086`](https://github.com/mastra-ai/mastra/commit/7bf308663f0115ca74ad20554ade740f06640859), [`a8dd139`](https://github.com/mastra-ai/mastra/commit/a8dd1391a9fe9a6632c25809ef236980afa9a020), [`e5786be`](https://github.com/mastra-ai/mastra/commit/e5786be02bb903073082bd9d6da880ebaacc343f), [`2093fbd`](https://github.com/mastra-ai/mastra/commit/2093fbd53bb744bae19ec89f6d73db9a66fbe8a7), [`e7a5da4`](https://github.com/mastra-ai/mastra/commit/e7a5da4ef8e4dd452d2f232961b4e682a85ffe43), [`7b4393d`](https://github.com/mastra-ai/mastra/commit/7b4393d557411fdcf07b0e30e5acaf7cc85154ae)]:
43
+ - @mastra/core@1.58.0-alpha.1
44
+
3
45
  ## 1.14.0
4
46
 
5
47
  ### Minor Changes
@@ -3,7 +3,7 @@ name: mastra-clickhouse
3
3
  description: Documentation for @mastra/clickhouse. Use when working with @mastra/clickhouse APIs, configuration, or implementation.
4
4
  metadata:
5
5
  package: "@mastra/clickhouse"
6
- version: "1.14.0"
6
+ version: "1.15.0-alpha.1"
7
7
  ---
8
8
 
9
9
  ## When to use
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.14.0",
2
+ "version": "1.15.0-alpha.1",
3
3
  "package": "@mastra/clickhouse",
4
4
  "exports": {},
5
5
  "modules": {}
@@ -251,6 +251,64 @@ const memoryStore = await storage.getStore('memory')
251
251
  const thread = await memoryStore?.getThreadById({ threadId: '...' })
252
252
  ```
253
253
 
254
+ ## Closing connections
255
+
256
+ `close()` releases the connections of the stores a composite was built from: the `default` and `editor` stores, plus any domain that owns its own client. Each store is closed once, even when it backs several domains. When passed to the Mastra class, `close()` is called by `shutdown()`:
257
+
258
+ ```typescript
259
+ import { MastraCompositeStore } from '@mastra/core/storage'
260
+ import { PostgresStore } from '@mastra/pg'
261
+ import { Mastra } from '@mastra/core'
262
+
263
+ const pgStore = new PostgresStore({
264
+ id: 'pg-storage',
265
+ connectionString: process.env.DATABASE_URL,
266
+ })
267
+
268
+ export const mastra = new Mastra({
269
+ storage: new MastraCompositeStore({ id: 'composite', default: pgStore }),
270
+ })
271
+
272
+ process.on('SIGTERM', async () => {
273
+ // Releases the Postgres pool, so the process can exit
274
+ await mastra.shutdown()
275
+ })
276
+ ```
277
+
278
+ A store you construct only to supply a domain isn't reachable through the composite. Keep a reference to it and close it yourself:
279
+
280
+ ```typescript
281
+ import { MastraCompositeStore } from '@mastra/core/storage'
282
+ import { ClickhouseStore } from '@mastra/clickhouse'
283
+ import { PostgresStore } from '@mastra/pg'
284
+ import { Mastra } from '@mastra/core'
285
+
286
+ const pgStore = new PostgresStore({
287
+ id: 'pg-storage',
288
+ connectionString: process.env.DATABASE_URL,
289
+ })
290
+
291
+ const clickhouseStore = new ClickhouseStore({
292
+ id: 'clickhouse-storage',
293
+ url: process.env.CLICKHOUSE_URL,
294
+ username: process.env.CLICKHOUSE_USERNAME,
295
+ password: process.env.CLICKHOUSE_PASSWORD,
296
+ })
297
+
298
+ export const mastra = new Mastra({
299
+ storage: new MastraCompositeStore({
300
+ id: 'composite',
301
+ default: pgStore,
302
+ domains: { observability: clickhouseStore.stores?.observability },
303
+ }),
304
+ })
305
+
306
+ process.on('SIGTERM', async () => {
307
+ await mastra.shutdown()
308
+ await clickhouseStore.close()
309
+ })
310
+ ```
311
+
254
312
  ## Use cases
255
313
 
256
314
  ### Separate databases for different workloads
package/dist/index.cjs CHANGED
@@ -1185,7 +1185,10 @@ var MemoryStorageClickhouse = class extends _mastra_core_storage.MemoryStorage {
1185
1185
  hasMore: false
1186
1186
  };
1187
1187
  if (perPageForQuery === 0 && include && include.length > 0) {
1188
- const includeResult = await this._getIncludedMessages({ include });
1188
+ const includeResult = await this._getIncludedMessages({
1189
+ include,
1190
+ resourceId
1191
+ });
1189
1192
  const list = new _mastra_core_agent.MessageList().add(includeResult, "memory");
1190
1193
  return {
1191
1194
  messages: this._sortMessages(list.get.all.db(), field, direction),
@@ -1252,7 +1255,10 @@ var MemoryStorageClickhouse = class extends _mastra_core_storage.MemoryStorage {
1252
1255
  };
1253
1256
  const messageIds = new Set(paginatedMessages.map((m) => m.id));
1254
1257
  if (include && include.length > 0) {
1255
- const includeMessages = await this._getIncludedMessages({ include });
1258
+ const includeMessages = await this._getIncludedMessages({
1259
+ include,
1260
+ resourceId
1261
+ });
1256
1262
  for (const includeMsg of includeMessages) if (!messageIds.has(includeMsg.id)) {
1257
1263
  paginatedMessages.push(includeMsg);
1258
1264
  messageIds.add(includeMsg.id);
@@ -1270,6 +1276,7 @@ var MemoryStorageClickhouse = class extends _mastra_core_storage.MemoryStorage {
1270
1276
  hasMore: metadataFilter && perPageForResponse !== false ? offset + paginatedCount < total : perPageForResponse === false ? false : allThreadMessagesReturned ? false : offset + paginatedCount < total
1271
1277
  };
1272
1278
  } catch (error) {
1279
+ if (error instanceof _mastra_core_error.MastraError && error.category === _mastra_core_error.ErrorCategory.USER) throw error;
1273
1280
  const mastraError = new _mastra_core_error.MastraError({
1274
1281
  id: (0, _mastra_core_storage.createStorageErrorId)("CLICKHOUSE", "LIST_MESSAGES", "FAILED"),
1275
1282
  domain: _mastra_core_error.ErrorDomain.STORAGE,
@@ -1281,13 +1288,7 @@ var MemoryStorageClickhouse = class extends _mastra_core_storage.MemoryStorage {
1281
1288
  }, error);
1282
1289
  this.logger?.error?.(mastraError.toString());
1283
1290
  this.logger?.trackException?.(mastraError);
1284
- return {
1285
- messages: [],
1286
- total: 0,
1287
- page,
1288
- perPage: perPageForResponse,
1289
- hasMore: false
1290
- };
1291
+ throw mastraError;
1291
1292
  }
1292
1293
  }
1293
1294
  _sortMessages(messages, field, direction) {
@@ -1300,15 +1301,24 @@ var MemoryStorageClickhouse = class extends _mastra_core_storage.MemoryStorage {
1300
1301
  return direction === "ASC" ? String(aValue).localeCompare(String(bValue)) : String(bValue).localeCompare(String(aValue));
1301
1302
  });
1302
1303
  }
1303
- async _getIncludedMessages({ include }) {
1304
+ /**
1305
+ * Fetches the messages named by `include` together with their surrounding context.
1306
+ *
1307
+ * @param include - Message ids to pin, each with an optional before/after window.
1308
+ * @param resourceId - When set, restricts both the pinned messages and their context
1309
+ * to that resource so an id from another resource returns nothing.
1310
+ */
1311
+ async _getIncludedMessages({ include, resourceId }) {
1304
1312
  if (!include || include.length === 0) return [];
1305
1313
  const targetIds = include.map((inc) => inc.id).filter(Boolean);
1306
1314
  if (targetIds.length === 0) return [];
1307
1315
  const { messages: targetDocs } = await this.listMessagesById({ messageIds: targetIds });
1308
- const targetMap = new Map(targetDocs.map((msg) => [msg.id, {
1316
+ const scopedTargetDocs = resourceId ? targetDocs.filter((msg) => msg.resourceId === resourceId) : targetDocs;
1317
+ const targetMap = new Map(scopedTargetDocs.map((msg) => [msg.id, {
1309
1318
  threadId: msg.threadId,
1310
1319
  createdAt: msg.createdAt
1311
1320
  }]));
1321
+ const resourceCondition = resourceId ? ` AND "resourceId" = {var_resource:String}` : "";
1312
1322
  const unionQueries = [];
1313
1323
  const params = {};
1314
1324
  let paramIdx = 1;
@@ -1323,7 +1333,7 @@ var MemoryStorageClickhouse = class extends _mastra_core_storage.MemoryStorage {
1323
1333
  SELECT id, content, role, type, "createdAt", thread_id AS "threadId", "resourceId"
1324
1334
  FROM "${_mastra_core_storage.TABLE_MESSAGES}"
1325
1335
  WHERE thread_id = {${threadParam}:String}
1326
- AND createdAt <= parseDateTime64BestEffort({${createdAtParam}:String}, 3)
1336
+ AND createdAt <= parseDateTime64BestEffort({${createdAtParam}:String}, 3)${resourceCondition}
1327
1337
  ORDER BY createdAt DESC, id DESC
1328
1338
  LIMIT {${limitParam}:Int64}
1329
1339
  `);
@@ -1339,7 +1349,7 @@ var MemoryStorageClickhouse = class extends _mastra_core_storage.MemoryStorage {
1339
1349
  SELECT id, content, role, type, "createdAt", thread_id AS "threadId", "resourceId"
1340
1350
  FROM "${_mastra_core_storage.TABLE_MESSAGES}"
1341
1351
  WHERE thread_id = {${threadParam2}:String}
1342
- AND createdAt > parseDateTime64BestEffort({${createdAtParam2}:String}, 3)
1352
+ AND createdAt > parseDateTime64BestEffort({${createdAtParam2}:String}, 3)${resourceCondition}
1343
1353
  ORDER BY createdAt ASC, id ASC
1344
1354
  LIMIT {${limitParam2}:Int64}
1345
1355
  `);
@@ -1350,6 +1360,7 @@ var MemoryStorageClickhouse = class extends _mastra_core_storage.MemoryStorage {
1350
1360
  }
1351
1361
  }
1352
1362
  if (unionQueries.length === 0) return [];
1363
+ if (resourceId) params.var_resource = resourceId;
1353
1364
  let finalQuery;
1354
1365
  if (unionQueries.length === 1) finalQuery = unionQueries[0];
1355
1366
  else finalQuery = `SELECT * FROM (${unionQueries.join(" UNION ALL ")}) ORDER BY "createdAt" ASC, id ASC`;
@@ -3873,6 +3884,7 @@ function rowToSpanRecord(row) {
3873
3884
  function rowToLightSpanRecord(row) {
3874
3885
  const startedAt = toDate(row.startedAt);
3875
3886
  const endedAt = row.isEvent ? startedAt : toDateOrNull(row.endedAt);
3887
+ const error = parseJson(row.error) ?? void 0;
3876
3888
  return {
3877
3889
  traceId: row.traceId,
3878
3890
  spanId: row.spanId,
@@ -3885,7 +3897,13 @@ function rowToLightSpanRecord(row) {
3885
3897
  entityType: nullableEntityType(row.entityType),
3886
3898
  entityId: nullableString(row.entityId),
3887
3899
  entityName: nullableString(row.entityName),
3888
- error: parseJson(row.error) ?? void 0,
3900
+ error,
3901
+ status: (0, _mastra_core_storage.computeTraceStatus)({
3902
+ error,
3903
+ endedAt
3904
+ }),
3905
+ metadata: parseJson(row.metadataRaw) ?? void 0,
3906
+ inputPreview: (0, _mastra_core_storage.buildInputPreview)(row.input ?? null),
3889
3907
  createdAt: startedAt,
3890
3908
  updatedAt: null
3891
3909
  };
@@ -6208,93 +6226,48 @@ async function getRootSpan(client, args) {
6208
6226
  return { span: rowToSpanRecord(rows[0]) };
6209
6227
  }
6210
6228
  /**
6211
- * Shared page-mode helper used by listTracesLight.
6229
+ * Columns a trace list renders. `input` is selected only so the row mapper can
6230
+ * derive a short `inputPreview` at read time (see `rowToLightSpanRecord`); the
6231
+ * raw blob itself never leaves the store.
6212
6232
  */
6213
- async function listTraceRows(client, args, selectClause, mapRows) {
6214
- const { filters, pagination, orderBy } = _mastra_core_storage.listTracesArgsSchema.parse(args);
6215
- const page = pagination?.page ?? 0;
6216
- const perPage = pagination?.perPage ?? 10;
6217
- const { conditions, params } = buildTraceFilterConditions(filters, "r");
6218
- if (filters?.hasChildError != null) if (filters.hasChildError) conditions.push(`EXISTS (
6219
- SELECT 1 FROM ${TABLE_SPAN_EVENTS} c
6220
- WHERE c.traceId = r.traceId
6221
- AND c.parentSpanId IS NOT NULL
6222
- AND c.error IS NOT NULL
6223
- )`);
6224
- else conditions.push(`NOT EXISTS (
6225
- SELECT 1 FROM ${TABLE_SPAN_EVENTS} c
6226
- WHERE c.traceId = r.traceId
6227
- AND c.parentSpanId IS NOT NULL
6228
- AND c.error IS NOT NULL
6229
- )`);
6230
- const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
6231
- const orderClause = buildTraceOrderByClause(orderBy);
6232
- const countRows = await (await client.query({
6233
- query: `
6234
- SELECT count() as cnt FROM (
6235
- SELECT dedupeKey
6236
- FROM ${TABLE_TRACE_ROOTS} r
6237
- ${whereClause}
6238
- ORDER BY dedupeKey
6239
- LIMIT 1 BY dedupeKey
6240
- )
6241
- `,
6242
- query_params: params,
6243
- format: "JSONEachRow",
6244
- clickhouse_settings: CH_SETTINGS
6245
- })).json();
6246
- const total = Number(countRows[0]?.cnt ?? 0);
6247
- if (total === 0) return {
6248
- pagination: {
6249
- total: 0,
6250
- page,
6251
- perPage,
6252
- hasMore: false
6253
- },
6254
- spans: []
6255
- };
6256
- const rows = await (await client.query({
6257
- query: `
6258
- SELECT ${selectClause} FROM (
6259
- SELECT ${selectClause}
6260
- FROM ${TABLE_TRACE_ROOTS} r
6261
- ${whereClause}
6262
- ORDER BY dedupeKey
6263
- LIMIT 1 BY dedupeKey
6264
- )
6265
- ORDER BY ${orderClause}
6266
- LIMIT {limit:UInt32}
6267
- OFFSET {offset:UInt32}
6268
- `,
6269
- query_params: {
6270
- ...params,
6271
- limit: perPage,
6272
- offset: page * perPage
6273
- },
6274
- format: "JSONEachRow",
6275
- clickhouse_settings: CH_SETTINGS
6276
- })).json();
6277
- return {
6278
- pagination: {
6279
- total,
6280
- page,
6281
- perPage,
6282
- hasMore: (page + 1) * perPage < total
6283
- },
6284
- spans: mapRows(rows)
6285
- };
6286
- }
6233
+ const LIGHT_TRACE_ROOT_FIELDS = [
6234
+ "traceId",
6235
+ "spanId",
6236
+ "parentSpanId",
6237
+ "name",
6238
+ "spanType",
6239
+ "isEvent",
6240
+ "startedAt",
6241
+ "endedAt",
6242
+ "entityType",
6243
+ "entityId",
6244
+ "entityName",
6245
+ "error",
6246
+ "metadataRaw",
6247
+ "input"
6248
+ ];
6249
+ const FULL_PROJECTION = {
6250
+ innerSelect: "*",
6251
+ outerSelect: "*",
6252
+ deltaSelect: "r.* EXCEPT(startedAt, traceId, dedupeKey)"
6253
+ };
6254
+ const LIGHT_PROJECTION = {
6255
+ innerSelect: ["dedupeKey", ...LIGHT_TRACE_ROOT_FIELDS].join(", "),
6256
+ outerSelect: LIGHT_TRACE_ROOT_FIELDS.join(", "),
6257
+ deltaSelect: LIGHT_TRACE_ROOT_FIELDS.filter((field) => field !== "startedAt" && field !== "traceId").map((field) => `r.${field}`).join(", ")
6258
+ };
6287
6259
  /**
6288
- * List traces with optional filtering, pagination, and ordering.
6260
+ * Shared implementation behind listTraces and listTracesLight.
6289
6261
  *
6290
6262
  * Reads from trace_roots (root spans only).
6291
- * Uses two-stage query for ReplacingMergeTree deduplication:
6263
+ * Page mode uses a two-stage query for ReplacingMergeTree deduplication:
6292
6264
  * Inner: filter + deterministic ORDER BY + LIMIT 1 BY dedupeKey
6293
6265
  * Outer: final ordering + pagination
6266
+ * Delta mode joins the append-only delta table and returns only rows past the cursor.
6294
6267
  *
6295
6268
  * hasChildError is handled via EXISTS subquery against span_events.
6296
6269
  */
6297
- async function listTraces(client, args, strategy) {
6270
+ async function listTraceRows(client, args, strategy, projection, mapRows) {
6298
6271
  const { mode, filters, pagination, orderBy, after, limit } = _mastra_core_storage.listTracesArgsSchema.parse(args);
6299
6272
  const page = pagination?.page ?? 0;
6300
6273
  const perPage = pagination?.perPage ?? 10;
@@ -6324,10 +6297,11 @@ async function listTraces(client, args, strategy) {
6324
6297
  },
6325
6298
  deltaCursor: streamHeadCursor
6326
6299
  };
6327
- const rows = await queryTracesAfterCursor(client, whereClause, params, limit, validateCursorId(after));
6300
+ const afterCursor = validateCursorId(after);
6301
+ const rows = await queryTracesAfterCursor(client, projection.deltaSelect, whereClause, params, limit, afterCursor);
6328
6302
  const visibleRows = rows.slice(0, limit);
6329
6303
  return {
6330
- spans: (0, _mastra_core_storage.toTraceSpans)(visibleRows.map(rowToSpanRecord)),
6304
+ spans: mapRows(visibleRows),
6331
6305
  delta: {
6332
6306
  limit,
6333
6307
  hasMore: rows.length > limit
@@ -6362,10 +6336,10 @@ async function listTraces(client, args, strategy) {
6362
6336
  spans: [],
6363
6337
  ...deltaCursorEnabled ? { deltaCursor: currentDeltaCursor } : {}
6364
6338
  };
6365
- const spans = (await (await client.query({
6339
+ const rows = await (await client.query({
6366
6340
  query: `
6367
- SELECT * FROM (
6368
- SELECT *
6341
+ SELECT ${projection.outerSelect} FROM (
6342
+ SELECT ${projection.innerSelect}
6369
6343
  FROM ${TABLE_TRACE_ROOTS} r
6370
6344
  ${whereClause}
6371
6345
  ORDER BY dedupeKey
@@ -6382,7 +6356,7 @@ async function listTraces(client, args, strategy) {
6382
6356
  },
6383
6357
  format: "JSONEachRow",
6384
6358
  clickhouse_settings: CH_SETTINGS
6385
- })).json()).map(rowToSpanRecord);
6359
+ })).json();
6386
6360
  return {
6387
6361
  pagination: {
6388
6362
  total,
@@ -6390,32 +6364,27 @@ async function listTraces(client, args, strategy) {
6390
6364
  perPage,
6391
6365
  hasMore: (page + 1) * perPage < total
6392
6366
  },
6393
- spans: (0, _mastra_core_storage.toTraceSpans)(spans),
6367
+ spans: mapRows(rows),
6394
6368
  ...deltaCursorEnabled ? { deltaCursor: currentDeltaCursor } : {}
6395
6369
  };
6396
6370
  }
6397
- const LIGHT_TRACE_ROOT_COLUMNS = [
6398
- "traceId",
6399
- "spanId",
6400
- "parentSpanId",
6401
- "name",
6402
- "spanType",
6403
- "isEvent",
6404
- "startedAt",
6405
- "endedAt",
6406
- "entityType",
6407
- "entityId",
6408
- "entityName",
6409
- "error"
6410
- ].join(", ");
6411
- async function listTracesLight(client, args) {
6412
- return listTraceRows(client, args, LIGHT_TRACE_ROOT_COLUMNS, (rows) => rows.map(rowToLightSpanRecord));
6371
+ /** List traces with optional filtering, pagination, and ordering. */
6372
+ async function listTraces(client, args, strategy) {
6373
+ return listTraceRows(client, args, strategy, FULL_PROJECTION, (rows) => (0, _mastra_core_storage.toTraceSpans)(rows.map(rowToSpanRecord)));
6374
+ }
6375
+ /**
6376
+ * List traces projecting only the columns a trace list renders.
6377
+ * Skips the attributes/output blobs and reduces `input` to a short preview in
6378
+ * the mapper, so the response payload stays flat as traces grow.
6379
+ */
6380
+ async function listTracesLight(client, args, strategy) {
6381
+ return listTraceRows(client, args, strategy, LIGHT_PROJECTION, (rows) => rows.map(rowToLightSpanRecord));
6413
6382
  }
6414
- async function queryTracesAfterCursor(client, whereClause, params, limit, cursorId) {
6383
+ async function queryTracesAfterCursor(client, deltaSelect, whereClause, params, limit, cursorId) {
6415
6384
  return await (await client.query({
6416
6385
  query: `
6417
6386
  SELECT
6418
- r.* EXCEPT(startedAt, traceId, dedupeKey),
6387
+ ${deltaSelect},
6419
6388
  r.startedAt AS startedAt,
6420
6389
  r.traceId AS traceId,
6421
6390
  r.dedupeKey AS dedupeKey,
@@ -7392,7 +7361,7 @@ var ObservabilityStorageClickhouseVNext = class extends _mastra_core_storage.Obs
7392
7361
  }
7393
7362
  async listTracesLight(args) {
7394
7363
  try {
7395
- return await listTracesLight(this.#client, args);
7364
+ return await listTracesLight(this.#client, args, this.#deltaCursorStrategy);
7396
7365
  } catch (error) {
7397
7366
  if (error instanceof _mastra_core_error.MastraError) throw error;
7398
7367
  throw new _mastra_core_error.MastraError({