@mastra/duckdb 1.0.1 → 1.1.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 (48) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/LICENSE.md +15 -0
  3. package/dist/chunk-37GBWD4M.js +195 -0
  4. package/dist/chunk-37GBWD4M.js.map +1 -0
  5. package/dist/chunk-S2AWBPTS.cjs +198 -0
  6. package/dist/chunk-S2AWBPTS.cjs.map +1 -0
  7. package/dist/docs/SKILL.md +2 -2
  8. package/dist/docs/assets/SOURCE_MAP.json +8 -2
  9. package/dist/docs/references/reference-vectors-duckdb.md +46 -46
  10. package/dist/index.cjs +241 -4
  11. package/dist/index.cjs.map +1 -1
  12. package/dist/index.d.ts +5 -2
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +238 -6
  15. package/dist/index.js.map +1 -1
  16. package/dist/observability-PW6J27KS.js +1675 -0
  17. package/dist/observability-PW6J27KS.js.map +1 -0
  18. package/dist/observability-W2QRBK56.cjs +1677 -0
  19. package/dist/observability-W2QRBK56.cjs.map +1 -0
  20. package/dist/storage/db/index.d.ts +46 -0
  21. package/dist/storage/db/index.d.ts.map +1 -0
  22. package/dist/storage/domains/observability/ddl.d.ts +25 -0
  23. package/dist/storage/domains/observability/ddl.d.ts.map +1 -0
  24. package/dist/storage/domains/observability/discovery.d.ts +13 -0
  25. package/dist/storage/domains/observability/discovery.d.ts.map +1 -0
  26. package/dist/storage/domains/observability/feedback.d.ts +9 -0
  27. package/dist/storage/domains/observability/feedback.d.ts.map +1 -0
  28. package/dist/storage/domains/observability/filters.d.ts +27 -0
  29. package/dist/storage/domains/observability/filters.d.ts.map +1 -0
  30. package/dist/storage/domains/observability/helpers.d.ts +14 -0
  31. package/dist/storage/domains/observability/helpers.d.ts.map +1 -0
  32. package/dist/storage/domains/observability/index.d.ts +54 -0
  33. package/dist/storage/domains/observability/index.d.ts.map +1 -0
  34. package/dist/storage/domains/observability/logs.d.ts +7 -0
  35. package/dist/storage/domains/observability/logs.d.ts.map +1 -0
  36. package/dist/storage/domains/observability/metrics.d.ts +21 -0
  37. package/dist/storage/domains/observability/metrics.d.ts.map +1 -0
  38. package/dist/storage/domains/observability/scores.d.ts +9 -0
  39. package/dist/storage/domains/observability/scores.d.ts.map +1 -0
  40. package/dist/storage/domains/observability/tracing.d.ts +17 -0
  41. package/dist/storage/domains/observability/tracing.d.ts.map +1 -0
  42. package/dist/storage/index.d.ts +101 -0
  43. package/dist/storage/index.d.ts.map +1 -0
  44. package/dist/vector/filter-builder.d.ts +1 -0
  45. package/dist/vector/filter-builder.d.ts.map +1 -1
  46. package/dist/vector/index.d.ts +9 -0
  47. package/dist/vector/index.d.ts.map +1 -1
  48. package/package.json +7 -7
@@ -0,0 +1,1677 @@
1
+ 'use strict';
2
+
3
+ var chunkS2AWBPTS_cjs = require('./chunk-S2AWBPTS.cjs');
4
+ var storage = require('@mastra/core/storage');
5
+ var observability = require('@mastra/core/observability');
6
+ var utils = require('@mastra/core/utils');
7
+
8
+ // src/storage/domains/observability/ddl.ts
9
+ var SPAN_EVENTS_DDL = `
10
+ CREATE TABLE IF NOT EXISTS span_events (
11
+ -- Event metadata
12
+ eventType VARCHAR NOT NULL,
13
+ timestamp TIMESTAMP NOT NULL,
14
+
15
+ -- IDs
16
+ traceId VARCHAR NOT NULL,
17
+ spanId VARCHAR NOT NULL,
18
+ parentSpanId VARCHAR,
19
+ experimentId VARCHAR,
20
+
21
+ -- Entity
22
+ entityType VARCHAR,
23
+ entityId VARCHAR,
24
+ entityName VARCHAR,
25
+
26
+ -- Context
27
+ userId VARCHAR,
28
+ organizationId VARCHAR,
29
+ resourceId VARCHAR,
30
+ runId VARCHAR,
31
+ sessionId VARCHAR,
32
+ threadId VARCHAR,
33
+ requestId VARCHAR,
34
+ environment VARCHAR,
35
+ source VARCHAR,
36
+ serviceName VARCHAR,
37
+ requestContext JSON,
38
+
39
+ -- Span-specific scalars
40
+ name VARCHAR,
41
+ spanType VARCHAR,
42
+ isEvent BOOLEAN,
43
+ endedAt TIMESTAMP,
44
+
45
+ -- JSON fields
46
+ attributes JSON,
47
+ metadata JSON,
48
+ tags JSON,
49
+ scope JSON,
50
+ links JSON,
51
+ input JSON,
52
+ output JSON,
53
+ error JSON
54
+ )`;
55
+ var METRIC_EVENTS_DDL = `
56
+ CREATE TABLE IF NOT EXISTS metric_events (
57
+ -- Event metadata
58
+ timestamp TIMESTAMP NOT NULL,
59
+
60
+ -- IDs
61
+ traceId VARCHAR,
62
+ spanId VARCHAR,
63
+ experimentId VARCHAR,
64
+
65
+ -- Entity hierarchy
66
+ entityType VARCHAR,
67
+ entityId VARCHAR,
68
+ entityName VARCHAR,
69
+ parentEntityType VARCHAR,
70
+ parentEntityId VARCHAR,
71
+ parentEntityName VARCHAR,
72
+ rootEntityType VARCHAR,
73
+ rootEntityId VARCHAR,
74
+ rootEntityName VARCHAR,
75
+
76
+ -- Context
77
+ userId VARCHAR,
78
+ organizationId VARCHAR,
79
+ resourceId VARCHAR,
80
+ runId VARCHAR,
81
+ sessionId VARCHAR,
82
+ threadId VARCHAR,
83
+ requestId VARCHAR,
84
+ environment VARCHAR,
85
+ source VARCHAR,
86
+ serviceName VARCHAR,
87
+
88
+ -- Metric-specific scalars
89
+ name VARCHAR NOT NULL,
90
+ value DOUBLE NOT NULL,
91
+ provider VARCHAR,
92
+ model VARCHAR,
93
+ estimatedCost DOUBLE,
94
+ costUnit VARCHAR,
95
+
96
+ -- JSON fields
97
+ tags JSON,
98
+ labels JSON,
99
+ costMetadata JSON,
100
+ metadata JSON,
101
+ scope JSON
102
+ )`;
103
+ var LOG_EVENTS_DDL = `
104
+ CREATE TABLE IF NOT EXISTS log_events (
105
+ -- Event metadata
106
+ timestamp TIMESTAMP NOT NULL,
107
+
108
+ -- IDs
109
+ traceId VARCHAR,
110
+ spanId VARCHAR,
111
+ experimentId VARCHAR,
112
+
113
+ -- Entity hierarchy
114
+ entityType VARCHAR,
115
+ entityId VARCHAR,
116
+ entityName VARCHAR,
117
+ parentEntityType VARCHAR,
118
+ parentEntityId VARCHAR,
119
+ parentEntityName VARCHAR,
120
+ rootEntityType VARCHAR,
121
+ rootEntityId VARCHAR,
122
+ rootEntityName VARCHAR,
123
+
124
+ -- Context
125
+ userId VARCHAR,
126
+ organizationId VARCHAR,
127
+ resourceId VARCHAR,
128
+ runId VARCHAR,
129
+ sessionId VARCHAR,
130
+ threadId VARCHAR,
131
+ requestId VARCHAR,
132
+ environment VARCHAR,
133
+ source VARCHAR,
134
+ serviceName VARCHAR,
135
+
136
+ -- Log-specific scalars
137
+ level VARCHAR NOT NULL,
138
+ message VARCHAR NOT NULL,
139
+
140
+ -- JSON fields
141
+ data JSON,
142
+ tags JSON,
143
+ metadata JSON,
144
+ scope JSON
145
+ )`;
146
+ var SCORE_EVENTS_DDL = `
147
+ CREATE TABLE IF NOT EXISTS score_events (
148
+ -- Event metadata
149
+ timestamp TIMESTAMP NOT NULL,
150
+
151
+ -- IDs
152
+ traceId VARCHAR NOT NULL,
153
+ spanId VARCHAR,
154
+ experimentId VARCHAR,
155
+ scoreTraceId VARCHAR,
156
+
157
+ -- Score-specific scalars
158
+ scorerId VARCHAR NOT NULL,
159
+ scorerVersion VARCHAR,
160
+ source VARCHAR,
161
+ score DOUBLE NOT NULL,
162
+ reason VARCHAR,
163
+
164
+ -- JSON fields
165
+ metadata JSON
166
+ )`;
167
+ var FEEDBACK_EVENTS_DDL = `
168
+ CREATE TABLE IF NOT EXISTS feedback_events (
169
+ -- Event metadata
170
+ timestamp TIMESTAMP NOT NULL,
171
+
172
+ -- IDs
173
+ traceId VARCHAR NOT NULL,
174
+ spanId VARCHAR,
175
+ experimentId VARCHAR,
176
+ userId VARCHAR,
177
+ sourceId VARCHAR,
178
+
179
+ -- Feedback-specific scalars
180
+ source VARCHAR NOT NULL,
181
+ feedbackType VARCHAR NOT NULL,
182
+ value VARCHAR NOT NULL,
183
+ comment VARCHAR,
184
+
185
+ -- JSON fields
186
+ metadata JSON
187
+ )`;
188
+ var ALL_DDL = [SPAN_EVENTS_DDL, METRIC_EVENTS_DDL, LOG_EVENTS_DDL, SCORE_EVENTS_DDL, FEEDBACK_EVENTS_DDL];
189
+ function unionDistinctQueries(selects, orderBy) {
190
+ return `${selects.join("\nUNION\n")}
191
+ ORDER BY ${orderBy}`;
192
+ }
193
+ async function getEntityTypes(db, _args) {
194
+ const rows = await db.query(
195
+ unionDistinctQueries(
196
+ [
197
+ `SELECT entityType FROM span_events WHERE entityType IS NOT NULL`,
198
+ `SELECT entityType FROM metric_events WHERE entityType IS NOT NULL`,
199
+ `SELECT entityType FROM log_events WHERE entityType IS NOT NULL`
200
+ ],
201
+ "entityType"
202
+ )
203
+ );
204
+ const validTypes = new Set(Object.values(observability.EntityType));
205
+ const typeSet = /* @__PURE__ */ new Set();
206
+ for (const row of rows) {
207
+ if (row.entityType && validTypes.has(row.entityType)) {
208
+ typeSet.add(row.entityType);
209
+ }
210
+ }
211
+ return { entityTypes: Array.from(typeSet).sort() };
212
+ }
213
+ async function getEntityNames(db, args) {
214
+ const buildSelect = (table) => {
215
+ const conditions = [`entityName IS NOT NULL`];
216
+ if (args.entityType) {
217
+ conditions.push(`entityType = ?`);
218
+ }
219
+ return `SELECT entityName FROM ${table} WHERE ${conditions.join(" AND ")}`;
220
+ };
221
+ const params = args.entityType ? [args.entityType, args.entityType, args.entityType] : [];
222
+ const rows = await db.query(
223
+ unionDistinctQueries(
224
+ [buildSelect("span_events"), buildSelect("metric_events"), buildSelect("log_events")],
225
+ "entityName"
226
+ ),
227
+ params
228
+ );
229
+ return { names: rows.map((r) => r.entityName) };
230
+ }
231
+ async function getServiceNames(db, _args) {
232
+ const rows = await db.query(
233
+ unionDistinctQueries(
234
+ [
235
+ `SELECT serviceName FROM span_events WHERE serviceName IS NOT NULL`,
236
+ `SELECT serviceName FROM metric_events WHERE serviceName IS NOT NULL`,
237
+ `SELECT serviceName FROM log_events WHERE serviceName IS NOT NULL`
238
+ ],
239
+ "serviceName"
240
+ )
241
+ );
242
+ return { serviceNames: rows.map((r) => r.serviceName) };
243
+ }
244
+ async function getEnvironments(db, _args) {
245
+ const rows = await db.query(
246
+ unionDistinctQueries(
247
+ [
248
+ `SELECT environment FROM span_events WHERE environment IS NOT NULL`,
249
+ `SELECT environment FROM metric_events WHERE environment IS NOT NULL`,
250
+ `SELECT environment FROM log_events WHERE environment IS NOT NULL`
251
+ ],
252
+ "environment"
253
+ )
254
+ );
255
+ return { environments: rows.map((r) => r.environment) };
256
+ }
257
+ async function getTags(db, args) {
258
+ const buildSelect = (table) => {
259
+ const conditions = [`tags IS NOT NULL`];
260
+ if (args.entityType) {
261
+ conditions.push(`entityType = ?`);
262
+ }
263
+ return `SELECT unnest(CAST(tags AS VARCHAR[])) AS tag FROM ${table} WHERE ${conditions.join(" AND ")}`;
264
+ };
265
+ const params = args.entityType ? [args.entityType, args.entityType, args.entityType] : [];
266
+ const rows = await db.query(
267
+ unionDistinctQueries([buildSelect("span_events"), buildSelect("metric_events"), buildSelect("log_events")], "tag"),
268
+ params
269
+ );
270
+ return { tags: rows.map((r) => r.tag) };
271
+ }
272
+ function buildJsonPath(key) {
273
+ try {
274
+ return `$.${utils.parseFieldKey(key)}`;
275
+ } catch {
276
+ const escaped = key.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
277
+ return `$."${escaped}"`;
278
+ }
279
+ }
280
+ function normalizeJsonFilterValue(value) {
281
+ if (value === void 0) return null;
282
+ if (typeof value === "string") return value;
283
+ const json = JSON.stringify(value);
284
+ return json ?? null;
285
+ }
286
+ function sanitizeColumn(column) {
287
+ return utils.parseFieldKey(column);
288
+ }
289
+ function buildWhereClause(filters, fieldMappings) {
290
+ if (!filters) return { clause: "", params: [] };
291
+ const conditions = [];
292
+ const params = [];
293
+ for (const [key, value] of Object.entries(filters)) {
294
+ if (value === void 0 || value === null) continue;
295
+ const column = sanitizeColumn(key);
296
+ if (key === "timestamp" || key === "startedAt" || key === "endedAt") {
297
+ const dateRange = value;
298
+ if (dateRange.start) {
299
+ const op = dateRange.startExclusive ? ">" : ">=";
300
+ conditions.push(`${column} ${op} ?`);
301
+ params.push(dateRange.start);
302
+ }
303
+ if (dateRange.end) {
304
+ const op = dateRange.endExclusive ? "<" : "<=";
305
+ conditions.push(`${column} ${op} ?`);
306
+ params.push(dateRange.end);
307
+ }
308
+ continue;
309
+ }
310
+ if (key === "labels") {
311
+ const labelsObj = value;
312
+ for (const [labelKey, labelValue] of Object.entries(labelsObj)) {
313
+ conditions.push(`json_extract_string(${column}, ?) = ?`);
314
+ params.push(buildJsonPath(labelKey), labelValue);
315
+ }
316
+ continue;
317
+ }
318
+ if (key === "tags") {
319
+ const tags = value;
320
+ for (const tag of tags) {
321
+ conditions.push(`list_contains(CAST(${column} AS VARCHAR[]), ?)`);
322
+ params.push(tag);
323
+ }
324
+ continue;
325
+ }
326
+ if (key === "status") {
327
+ const status = value;
328
+ if (status === "error") {
329
+ conditions.push(`error IS NOT NULL`);
330
+ } else if (status === "running") {
331
+ conditions.push(`endedAt IS NULL AND error IS NULL`);
332
+ } else if (status === "success") {
333
+ conditions.push(`endedAt IS NOT NULL AND error IS NULL`);
334
+ }
335
+ continue;
336
+ }
337
+ if (key === "hasChildError") {
338
+ continue;
339
+ }
340
+ if (key === "metadata" || key === "scope") {
341
+ const jsonObj = value;
342
+ for (const [jsonKey, jsonValue] of Object.entries(jsonObj)) {
343
+ const normalized = normalizeJsonFilterValue(jsonValue);
344
+ if (normalized === null) continue;
345
+ conditions.push(`json_extract_string(${column}, ?) = ?`);
346
+ params.push(buildJsonPath(jsonKey), normalized);
347
+ }
348
+ continue;
349
+ }
350
+ if (Array.isArray(value)) {
351
+ if (value.length === 0) continue;
352
+ const placeholders = value.map(() => "?").join(", ");
353
+ conditions.push(`${column} IN (${placeholders})`);
354
+ params.push(...value);
355
+ continue;
356
+ }
357
+ conditions.push(`${column} = ?`);
358
+ params.push(value);
359
+ }
360
+ const clause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
361
+ return { clause, params };
362
+ }
363
+ function buildOrderByClause(orderBy) {
364
+ if (!orderBy) return "";
365
+ const dir = orderBy.direction.toUpperCase();
366
+ if (dir !== "ASC" && dir !== "DESC") {
367
+ throw new Error(`Invalid sort direction: ${orderBy.direction}`);
368
+ }
369
+ const field = utils.parseFieldKey(orderBy.field);
370
+ return `ORDER BY ${field} ${dir}`;
371
+ }
372
+ function buildPaginationClause(pagination) {
373
+ if (!pagination) return { clause: "", params: [] };
374
+ if (!Number.isInteger(pagination.page) || pagination.page < 0) {
375
+ throw new Error(`Invalid page: ${pagination.page}`);
376
+ }
377
+ if (!Number.isInteger(pagination.perPage) || pagination.perPage <= 0) {
378
+ throw new Error(`Invalid perPage: ${pagination.perPage}`);
379
+ }
380
+ const offset = pagination.page * pagination.perPage;
381
+ return {
382
+ clause: `LIMIT ? OFFSET ?`,
383
+ params: [pagination.perPage, offset]
384
+ };
385
+ }
386
+
387
+ // src/storage/domains/observability/helpers.ts
388
+ var v = chunkS2AWBPTS_cjs.DuckDBConnection.sqlValue;
389
+ function jsonV(val) {
390
+ if (val === null || val === void 0) return "NULL";
391
+ return chunkS2AWBPTS_cjs.DuckDBConnection.sqlValue(JSON.stringify(val));
392
+ }
393
+ function toDate(val) {
394
+ if (val === null || val === void 0) {
395
+ throw new Error("Expected date value but received null/undefined");
396
+ }
397
+ const date = val instanceof Date ? val : new Date(String(val));
398
+ if (Number.isNaN(date.getTime())) {
399
+ throw new Error("Expected valid date but received invalid date");
400
+ }
401
+ return date;
402
+ }
403
+ function toDateOrNull(val) {
404
+ if (val === null || val === void 0) return null;
405
+ return val instanceof Date ? val : new Date(String(val));
406
+ }
407
+ function parseJson(value) {
408
+ if (value === null || value === void 0) return null;
409
+ if (typeof value === "string") {
410
+ try {
411
+ return JSON.parse(value);
412
+ } catch {
413
+ return value;
414
+ }
415
+ }
416
+ return value;
417
+ }
418
+ function parseJsonArray(value) {
419
+ if (value === null || value === void 0) return null;
420
+ const parsed = parseJson(value);
421
+ return Array.isArray(parsed) ? parsed : null;
422
+ }
423
+
424
+ // src/storage/domains/observability/feedback.ts
425
+ async function createFeedback(db, args) {
426
+ const f = args.feedback;
427
+ await db.execute(
428
+ `INSERT INTO feedback_events (timestamp, traceId, spanId, experimentId, userId, sourceId, source, feedbackType, value, comment, metadata)
429
+ VALUES (${[
430
+ v(f.timestamp),
431
+ v(f.traceId),
432
+ v(f.spanId ?? null),
433
+ v(f.experimentId ?? null),
434
+ v(f.userId ?? null),
435
+ v(f.sourceId ?? null),
436
+ v(f.source),
437
+ v(f.feedbackType),
438
+ v(String(f.value)),
439
+ v(f.comment ?? null),
440
+ jsonV(f.metadata)
441
+ ].join(", ")})`
442
+ );
443
+ }
444
+ async function batchCreateFeedback(db, args) {
445
+ if (args.feedbacks.length === 0) return;
446
+ const tuples = args.feedbacks.map(
447
+ (f) => `(${[
448
+ v(f.timestamp),
449
+ v(f.traceId),
450
+ v(f.spanId ?? null),
451
+ v(f.experimentId ?? null),
452
+ v(f.userId ?? null),
453
+ v(f.sourceId ?? null),
454
+ v(f.source),
455
+ v(f.feedbackType),
456
+ v(String(f.value)),
457
+ v(f.comment ?? null),
458
+ jsonV(f.metadata)
459
+ ].join(", ")})`
460
+ );
461
+ await db.execute(
462
+ `INSERT INTO feedback_events (timestamp, traceId, spanId, experimentId, userId, sourceId, source, feedbackType, value, comment, metadata)
463
+ VALUES ${tuples.join(",\n ")}`
464
+ );
465
+ }
466
+ async function listFeedback(db, args) {
467
+ const filters = args.filters ?? {};
468
+ const page = Number(args.pagination?.page ?? 0);
469
+ const perPage = Number(args.pagination?.perPage ?? 10);
470
+ const orderBy = { field: args.orderBy?.field ?? "timestamp", direction: args.orderBy?.direction ?? "DESC" };
471
+ const { clause: filterClause, params: filterParams } = buildWhereClause(filters);
472
+ const orderByClause = buildOrderByClause(orderBy);
473
+ const { clause: paginationClause, params: paginationParams } = buildPaginationClause({ page, perPage });
474
+ const countResult = await db.query(
475
+ `SELECT COUNT(*) as total FROM feedback_events ${filterClause}`,
476
+ filterParams
477
+ );
478
+ const total = Number(countResult[0]?.total ?? 0);
479
+ const rows = await db.query(`SELECT * FROM feedback_events ${filterClause} ${orderByClause} ${paginationClause}`, [
480
+ ...filterParams,
481
+ ...paginationParams
482
+ ]);
483
+ const feedback = rows.map((row) => {
484
+ const r = row;
485
+ const rawValue = r.value;
486
+ let value = rawValue;
487
+ const numValue = Number(rawValue);
488
+ if (!isNaN(numValue)) value = numValue;
489
+ return {
490
+ timestamp: toDate(r.timestamp),
491
+ traceId: r.traceId,
492
+ spanId: r.spanId ?? null,
493
+ experimentId: r.experimentId ?? null,
494
+ userId: r.userId ?? null,
495
+ sourceId: r.sourceId ?? null,
496
+ source: r.source,
497
+ feedbackType: r.feedbackType,
498
+ value,
499
+ comment: r.comment ?? null,
500
+ metadata: parseJson(r.metadata)
501
+ };
502
+ });
503
+ return {
504
+ pagination: { total, page, perPage, hasMore: (page + 1) * perPage < total },
505
+ feedback
506
+ };
507
+ }
508
+
509
+ // src/storage/domains/observability/logs.ts
510
+ var COLUMNS = [
511
+ "timestamp",
512
+ "level",
513
+ "message",
514
+ "data",
515
+ "traceId",
516
+ "spanId",
517
+ "entityType",
518
+ "entityId",
519
+ "entityName",
520
+ "parentEntityType",
521
+ "parentEntityId",
522
+ "parentEntityName",
523
+ "rootEntityType",
524
+ "rootEntityId",
525
+ "rootEntityName",
526
+ "userId",
527
+ "organizationId",
528
+ "resourceId",
529
+ "runId",
530
+ "sessionId",
531
+ "threadId",
532
+ "requestId",
533
+ "environment",
534
+ "source",
535
+ "serviceName",
536
+ "experimentId",
537
+ "tags",
538
+ "metadata",
539
+ "scope"
540
+ ];
541
+ var COLUMNS_SQL = COLUMNS.join(", ");
542
+ function rowToLogRecord(row) {
543
+ return {
544
+ timestamp: toDate(row.timestamp),
545
+ level: row.level,
546
+ message: row.message,
547
+ data: parseJson(row.data),
548
+ traceId: row.traceId ?? null,
549
+ spanId: row.spanId ?? null,
550
+ entityType: row.entityType ?? null,
551
+ entityId: row.entityId ?? null,
552
+ entityName: row.entityName ?? null,
553
+ parentEntityType: row.parentEntityType ?? null,
554
+ parentEntityId: row.parentEntityId ?? null,
555
+ parentEntityName: row.parentEntityName ?? null,
556
+ rootEntityType: row.rootEntityType ?? null,
557
+ rootEntityId: row.rootEntityId ?? null,
558
+ rootEntityName: row.rootEntityName ?? null,
559
+ userId: row.userId ?? null,
560
+ organizationId: row.organizationId ?? null,
561
+ resourceId: row.resourceId ?? null,
562
+ runId: row.runId ?? null,
563
+ sessionId: row.sessionId ?? null,
564
+ threadId: row.threadId ?? null,
565
+ requestId: row.requestId ?? null,
566
+ environment: row.environment ?? null,
567
+ source: row.source ?? null,
568
+ serviceName: row.serviceName ?? null,
569
+ experimentId: row.experimentId ?? null,
570
+ tags: parseJsonArray(row.tags),
571
+ metadata: parseJson(row.metadata),
572
+ scope: parseJson(row.scope)
573
+ };
574
+ }
575
+ async function batchCreateLogs(db, args) {
576
+ if (args.logs.length === 0) return;
577
+ const tuples = args.logs.map((log) => {
578
+ return `(${[
579
+ v(log.timestamp),
580
+ v(log.level),
581
+ v(log.message),
582
+ jsonV(log.data),
583
+ v(log.traceId ?? null),
584
+ v(log.spanId ?? null),
585
+ v(log.entityType ?? null),
586
+ v(log.entityId ?? null),
587
+ v(log.entityName ?? null),
588
+ v(log.parentEntityType ?? null),
589
+ v(log.parentEntityId ?? null),
590
+ v(log.parentEntityName ?? null),
591
+ v(log.rootEntityType ?? null),
592
+ v(log.rootEntityId ?? null),
593
+ v(log.rootEntityName ?? null),
594
+ v(log.userId ?? null),
595
+ v(log.organizationId ?? null),
596
+ v(log.resourceId ?? null),
597
+ v(log.runId ?? null),
598
+ v(log.sessionId ?? null),
599
+ v(log.threadId ?? null),
600
+ v(log.requestId ?? null),
601
+ v(log.environment ?? null),
602
+ v(log.source ?? null),
603
+ v(log.serviceName ?? null),
604
+ v(log.experimentId ?? null),
605
+ jsonV(log.tags),
606
+ jsonV(log.metadata),
607
+ jsonV(log.scope)
608
+ ].join(", ")})`;
609
+ });
610
+ await db.execute(`INSERT INTO log_events (${COLUMNS_SQL}) VALUES ${tuples.join(",\n")}`);
611
+ }
612
+ async function listLogs(db, args) {
613
+ const filters = args.filters ?? {};
614
+ const page = Number(args.pagination?.page ?? 0);
615
+ const perPage = Number(args.pagination?.perPage ?? 10);
616
+ const orderBy = { field: args.orderBy?.field ?? "timestamp", direction: args.orderBy?.direction ?? "DESC" };
617
+ const { clause: filterClause, params: filterParams } = buildWhereClause(filters);
618
+ const orderByClause = buildOrderByClause(orderBy);
619
+ const { clause: paginationClause, params: paginationParams } = buildPaginationClause({ page, perPage });
620
+ const countResult = await db.query(
621
+ `SELECT COUNT(*) as total FROM log_events ${filterClause}`,
622
+ filterParams
623
+ );
624
+ const total = Number(countResult[0]?.total ?? 0);
625
+ const rows = await db.query(`SELECT * FROM log_events ${filterClause} ${orderByClause} ${paginationClause}`, [
626
+ ...filterParams,
627
+ ...paginationParams
628
+ ]);
629
+ const logs = rows.map((row) => rowToLogRecord(row));
630
+ return {
631
+ pagination: { total, page, perPage, hasMore: (page + 1) * perPage < total },
632
+ logs
633
+ };
634
+ }
635
+ function getAggregationSql(aggregation, measure = "value") {
636
+ switch (aggregation) {
637
+ case "sum":
638
+ return `SUM(${measure})`;
639
+ case "avg":
640
+ return `AVG(${measure})`;
641
+ case "min":
642
+ return `MIN(${measure})`;
643
+ case "max":
644
+ return `MAX(${measure})`;
645
+ case "count":
646
+ return `CAST(COUNT(${measure}) AS DOUBLE)`;
647
+ case "last":
648
+ return `arg_max(${measure}, timestamp)`;
649
+ default:
650
+ return `SUM(${measure})`;
651
+ }
652
+ }
653
+ function getIntervalSql(interval) {
654
+ switch (interval) {
655
+ case "1m":
656
+ return "1 minute";
657
+ case "5m":
658
+ return "5 minutes";
659
+ case "15m":
660
+ return "15 minutes";
661
+ case "1h":
662
+ return "1 hour";
663
+ case "1d":
664
+ return "1 day";
665
+ default:
666
+ return "1 hour";
667
+ }
668
+ }
669
+ function buildMetricNameFilter(name) {
670
+ if (Array.isArray(name)) {
671
+ const placeholders = name.map(() => "?").join(", ");
672
+ return { clause: `name IN (${placeholders})`, params: name };
673
+ }
674
+ return { clause: `name = ?`, params: [name] };
675
+ }
676
+ var METRIC_COLUMNS = [
677
+ "timestamp",
678
+ "name",
679
+ "value",
680
+ "traceId",
681
+ "spanId",
682
+ "entityType",
683
+ "entityId",
684
+ "entityName",
685
+ "parentEntityType",
686
+ "parentEntityId",
687
+ "parentEntityName",
688
+ "rootEntityType",
689
+ "rootEntityId",
690
+ "rootEntityName",
691
+ "userId",
692
+ "organizationId",
693
+ "resourceId",
694
+ "runId",
695
+ "sessionId",
696
+ "threadId",
697
+ "requestId",
698
+ "environment",
699
+ "source",
700
+ "serviceName",
701
+ "experimentId",
702
+ "provider",
703
+ "model",
704
+ "estimatedCost",
705
+ "costUnit",
706
+ "tags",
707
+ "labels",
708
+ "costMetadata",
709
+ "metadata",
710
+ "scope"
711
+ ];
712
+ var METRIC_COLUMNS_SQL = METRIC_COLUMNS.join(", ");
713
+ var METRIC_COLUMN_SET = new Set(METRIC_COLUMNS);
714
+ var METRIC_LABEL_ONLY_GROUP_BY_EXCLUDED = /* @__PURE__ */ new Set(["metadata", "scope", "costMetadata", "tags"]);
715
+ function buildGroupByAlias(index) {
716
+ return `group_by_${index}`;
717
+ }
718
+ function toSeriesDisplayValue(value) {
719
+ return value === null || value === void 0 ? "" : String(value);
720
+ }
721
+ function getCostSummarySelect(prefix = "") {
722
+ const ref = (column) => `${prefix}${column}`;
723
+ return [
724
+ `SUM(${ref("estimatedCost")}) FILTER (WHERE ${ref("estimatedCost")} IS NOT NULL) AS estimatedCost`,
725
+ `,`,
726
+ `CASE`,
727
+ ` WHEN COUNT(DISTINCT ${ref("costUnit")}) FILTER (WHERE ${ref("costUnit")} IS NOT NULL) = 1`,
728
+ ` THEN MIN(${ref("costUnit")}) FILTER (WHERE ${ref("costUnit")} IS NOT NULL)`,
729
+ ` ELSE NULL`,
730
+ `END AS costUnit`
731
+ ].join(" ");
732
+ }
733
+ function normalizeCostSummaryRow(row) {
734
+ return {
735
+ estimatedCost: row.estimatedCost === null || row.estimatedCost === void 0 ? null : Number(row.estimatedCost),
736
+ costUnit: row.costUnit === null || row.costUnit === void 0 ? null : String(row.costUnit)
737
+ };
738
+ }
739
+ function buildCombinedWhereClause(nameClause, nameParams, filterClause, filterParams) {
740
+ const conditions = [nameClause];
741
+ const params = [...nameParams];
742
+ if (filterClause) {
743
+ conditions.push(filterClause.replace("WHERE ", ""));
744
+ params.push(...filterParams);
745
+ }
746
+ return { clause: `WHERE ${conditions.join(" AND ")}`, params };
747
+ }
748
+ function resolveGroupBy(groupBy) {
749
+ return groupBy.map((key, index) => {
750
+ if (METRIC_COLUMN_SET.has(key)) {
751
+ const parsed = utils.parseFieldKey(key);
752
+ if (METRIC_LABEL_ONLY_GROUP_BY_EXCLUDED.has(parsed)) {
753
+ throw new Error(`Invalid groupBy column(s): ${key}`);
754
+ }
755
+ return {
756
+ kind: "column",
757
+ key,
758
+ selectSql: `${parsed} AS "${key}"`,
759
+ groupSql: parsed,
760
+ resultKey: key
761
+ };
762
+ }
763
+ const labelPath = buildJsonPath(key).replace(/'/g, "''");
764
+ const labelExpr = `json_extract_string(labels, '${labelPath}')`;
765
+ const alias = buildGroupByAlias(index);
766
+ return {
767
+ kind: "label",
768
+ key,
769
+ selectSql: `${labelExpr} AS ${alias}`,
770
+ groupSql: alias,
771
+ resultKey: alias
772
+ };
773
+ });
774
+ }
775
+ function rowToMetricRecord(row) {
776
+ return {
777
+ timestamp: toDate(row.timestamp),
778
+ name: row.name,
779
+ value: Number(row.value),
780
+ traceId: row.traceId ?? null,
781
+ spanId: row.spanId ?? null,
782
+ entityType: row.entityType ?? null,
783
+ entityId: row.entityId ?? null,
784
+ entityName: row.entityName ?? null,
785
+ parentEntityType: row.parentEntityType ?? null,
786
+ parentEntityId: row.parentEntityId ?? null,
787
+ parentEntityName: row.parentEntityName ?? null,
788
+ rootEntityType: row.rootEntityType ?? null,
789
+ rootEntityId: row.rootEntityId ?? null,
790
+ rootEntityName: row.rootEntityName ?? null,
791
+ userId: row.userId ?? null,
792
+ organizationId: row.organizationId ?? null,
793
+ resourceId: row.resourceId ?? null,
794
+ runId: row.runId ?? null,
795
+ sessionId: row.sessionId ?? null,
796
+ threadId: row.threadId ?? null,
797
+ requestId: row.requestId ?? null,
798
+ environment: row.environment ?? null,
799
+ source: row.source ?? null,
800
+ serviceName: row.serviceName ?? null,
801
+ experimentId: row.experimentId ?? null,
802
+ provider: row.provider ?? null,
803
+ model: row.model ?? null,
804
+ estimatedCost: row.estimatedCost === null || row.estimatedCost === void 0 ? null : Number(row.estimatedCost),
805
+ costUnit: row.costUnit ?? null,
806
+ costMetadata: parseJson(row.costMetadata),
807
+ tags: parseJsonArray(row.tags),
808
+ labels: parseJson(row.labels) ?? {},
809
+ metadata: parseJson(row.metadata),
810
+ scope: parseJson(row.scope)
811
+ };
812
+ }
813
+ async function batchCreateMetrics(db, args) {
814
+ if (args.metrics.length === 0) return;
815
+ const tuples = args.metrics.map((m) => {
816
+ return `(${[
817
+ v(m.timestamp),
818
+ v(m.name),
819
+ v(m.value),
820
+ v(m.traceId ?? null),
821
+ v(m.spanId ?? null),
822
+ v(m.entityType ?? null),
823
+ v(m.entityId ?? null),
824
+ v(m.entityName ?? null),
825
+ v(m.parentEntityType ?? null),
826
+ v(m.parentEntityId ?? null),
827
+ v(m.parentEntityName ?? null),
828
+ v(m.rootEntityType ?? null),
829
+ v(m.rootEntityId ?? null),
830
+ v(m.rootEntityName ?? null),
831
+ v(m.userId ?? null),
832
+ v(m.organizationId ?? null),
833
+ v(m.resourceId ?? null),
834
+ v(m.runId ?? null),
835
+ v(m.sessionId ?? null),
836
+ v(m.threadId ?? null),
837
+ v(m.requestId ?? null),
838
+ v(m.environment ?? null),
839
+ v(m.source ?? null),
840
+ v(m.serviceName ?? null),
841
+ v(m.experimentId ?? null),
842
+ v(m.provider ?? null),
843
+ v(m.model ?? null),
844
+ v(m.estimatedCost ?? null),
845
+ v(m.costUnit ?? null),
846
+ jsonV(m.tags ?? null),
847
+ v(JSON.stringify(m.labels ?? {})),
848
+ jsonV(m.costMetadata ?? null),
849
+ jsonV(m.metadata ?? null),
850
+ jsonV(m.scope ?? null)
851
+ ].join(", ")})`;
852
+ });
853
+ await db.execute(`INSERT INTO metric_events (${METRIC_COLUMNS_SQL}) VALUES ${tuples.join(",\n")}`);
854
+ }
855
+ async function listMetrics(db, args) {
856
+ const filters = args.filters ?? {};
857
+ const page = Number(args.pagination?.page ?? 0);
858
+ const perPage = Number(args.pagination?.perPage ?? 10);
859
+ const orderBy = { field: args.orderBy?.field ?? "timestamp", direction: args.orderBy?.direction ?? "DESC" };
860
+ const { clause: filterClause, params: filterParams } = buildWhereClause(filters);
861
+ const orderByClause = buildOrderByClause(orderBy);
862
+ const { clause: paginationClause, params: paginationParams } = buildPaginationClause({ page, perPage });
863
+ const countResult = await db.query(
864
+ `SELECT COUNT(*) AS total FROM metric_events ${filterClause}`,
865
+ filterParams
866
+ );
867
+ const total = Number(countResult[0]?.total ?? 0);
868
+ const rows = await db.query(
869
+ `SELECT * FROM metric_events ${filterClause} ${orderByClause} ${paginationClause}`,
870
+ [...filterParams, ...paginationParams]
871
+ );
872
+ return {
873
+ pagination: { total, page, perPage, hasMore: (page + 1) * perPage < total },
874
+ metrics: rows.map((row) => rowToMetricRecord(row))
875
+ };
876
+ }
877
+ async function getMetricAggregate(db, args) {
878
+ const aggSql = getAggregationSql(args.aggregation);
879
+ const { clause: nameClause, params: nameParams } = buildMetricNameFilter(args.name);
880
+ const { clause: filterClause, params: filterParams } = buildWhereClause(
881
+ args.filters
882
+ );
883
+ const { clause: whereClause, params: allParams } = buildCombinedWhereClause(
884
+ nameClause,
885
+ nameParams,
886
+ filterClause,
887
+ filterParams
888
+ );
889
+ const sql = `SELECT ${aggSql} AS value, ${getCostSummarySelect()} FROM metric_events ${whereClause}`;
890
+ const result = await db.query(sql, allParams);
891
+ const row = result[0] ?? {};
892
+ const value = row.value === null || row.value === void 0 ? null : Number(row.value);
893
+ const costSummary = normalizeCostSummaryRow(row);
894
+ if (args.comparePeriod && args.filters?.timestamp) {
895
+ const ts = args.filters.timestamp;
896
+ if (ts.start && ts.end) {
897
+ const duration = ts.end.getTime() - ts.start.getTime();
898
+ let prevStart;
899
+ let prevEnd;
900
+ switch (args.comparePeriod) {
901
+ case "previous_period":
902
+ prevStart = new Date(ts.start.getTime() - duration);
903
+ prevEnd = new Date(ts.end.getTime() - duration);
904
+ break;
905
+ case "previous_day":
906
+ prevStart = new Date(ts.start.getTime() - 864e5);
907
+ prevEnd = new Date(ts.end.getTime() - 864e5);
908
+ break;
909
+ case "previous_week":
910
+ prevStart = new Date(ts.start.getTime() - 6048e5);
911
+ prevEnd = new Date(ts.end.getTime() - 6048e5);
912
+ break;
913
+ default:
914
+ prevStart = new Date(ts.start.getTime() - duration);
915
+ prevEnd = new Date(ts.end.getTime() - duration);
916
+ }
917
+ const prevFilters = {
918
+ ...args.filters ?? {},
919
+ timestamp: {
920
+ start: prevStart,
921
+ end: prevEnd,
922
+ startExclusive: ts.startExclusive,
923
+ endExclusive: ts.endExclusive
924
+ }
925
+ };
926
+ const { clause: prevFilterClause, params: prevFilterParams } = buildWhereClause(
927
+ prevFilters
928
+ );
929
+ const { clause: prevWhereClause, params: prevParams } = buildCombinedWhereClause(
930
+ nameClause,
931
+ nameParams,
932
+ prevFilterClause,
933
+ prevFilterParams
934
+ );
935
+ const prevSql = `SELECT ${aggSql} AS value, ${getCostSummarySelect()} FROM metric_events ${prevWhereClause}`;
936
+ const prevResult = await db.query(prevSql, prevParams);
937
+ const prevRow = prevResult[0] ?? {};
938
+ const previousValue = prevRow.value === null || prevRow.value === void 0 ? null : Number(prevRow.value);
939
+ const previousCostSummary = normalizeCostSummaryRow(prevRow);
940
+ let changePercent = null;
941
+ if (previousValue !== null && previousValue !== 0 && value !== null) {
942
+ changePercent = (value - previousValue) / Math.abs(previousValue) * 100;
943
+ }
944
+ let costChangePercent = null;
945
+ if (previousCostSummary.estimatedCost !== null && previousCostSummary.estimatedCost !== 0 && costSummary.estimatedCost !== null) {
946
+ costChangePercent = (costSummary.estimatedCost - previousCostSummary.estimatedCost) / Math.abs(previousCostSummary.estimatedCost) * 100;
947
+ }
948
+ return {
949
+ value,
950
+ estimatedCost: costSummary.estimatedCost,
951
+ costUnit: costSummary.costUnit,
952
+ previousValue,
953
+ previousEstimatedCost: previousCostSummary.estimatedCost,
954
+ changePercent,
955
+ costChangePercent
956
+ };
957
+ }
958
+ }
959
+ return { value, estimatedCost: costSummary.estimatedCost, costUnit: costSummary.costUnit };
960
+ }
961
+ async function getMetricBreakdown(db, args) {
962
+ const aggSql = getAggregationSql(args.aggregation);
963
+ const { clause: nameClause, params: nameParams } = buildMetricNameFilter(args.name);
964
+ const { clause: filterClause, params: filterParams } = buildWhereClause(
965
+ args.filters
966
+ );
967
+ const { clause: whereClause, params: allParams } = buildCombinedWhereClause(
968
+ nameClause,
969
+ nameParams,
970
+ filterClause,
971
+ filterParams
972
+ );
973
+ const resolvedGroupBy = resolveGroupBy(args.groupBy);
974
+ const selectGroupBy = resolvedGroupBy.map((entry) => entry.selectSql).join(", ");
975
+ const groupByCols = resolvedGroupBy.map((entry) => entry.groupSql).join(", ");
976
+ const sql = `SELECT ${selectGroupBy}, ${aggSql} AS value, ${getCostSummarySelect()} FROM metric_events ${whereClause} GROUP BY ${groupByCols} ORDER BY value DESC`;
977
+ const rows = await db.query(sql, allParams);
978
+ const groups = rows.map((row) => {
979
+ const dimensions = {};
980
+ for (const entry of resolvedGroupBy) {
981
+ const value = row[entry.resultKey];
982
+ dimensions[entry.key] = value === null || value === void 0 ? null : String(value);
983
+ }
984
+ const costSummary = normalizeCostSummaryRow(row);
985
+ return {
986
+ dimensions,
987
+ value: Number(row.value ?? 0),
988
+ estimatedCost: costSummary.estimatedCost,
989
+ costUnit: costSummary.costUnit
990
+ };
991
+ });
992
+ return { groups };
993
+ }
994
+ async function getMetricTimeSeries(db, args) {
995
+ const aggSql = getAggregationSql(args.aggregation);
996
+ const intervalSql = getIntervalSql(args.interval);
997
+ const { clause: nameClause, params: nameParams } = buildMetricNameFilter(args.name);
998
+ const { clause: filterClause, params: filterParams } = buildWhereClause(
999
+ args.filters
1000
+ );
1001
+ const { clause: whereClause, params: allParams } = buildCombinedWhereClause(
1002
+ nameClause,
1003
+ nameParams,
1004
+ filterClause,
1005
+ filterParams
1006
+ );
1007
+ if (args.groupBy && args.groupBy.length > 0) {
1008
+ const resolvedGroupBy = resolveGroupBy(args.groupBy);
1009
+ const selectGroupBy = resolvedGroupBy.map((entry) => entry.selectSql).join(", ");
1010
+ const groupByCols = resolvedGroupBy.map((entry) => entry.groupSql).join(", ");
1011
+ const sql2 = `
1012
+ SELECT time_bucket(INTERVAL '${intervalSql}', timestamp) AS bucket,
1013
+ ${selectGroupBy},
1014
+ ${aggSql} AS value,
1015
+ ${getCostSummarySelect()}
1016
+ FROM metric_events ${whereClause}
1017
+ GROUP BY bucket, ${groupByCols}
1018
+ ORDER BY bucket
1019
+ `;
1020
+ const rows2 = await db.query(sql2, allParams);
1021
+ const seriesMap = /* @__PURE__ */ new Map();
1022
+ for (const row of rows2) {
1023
+ const dimensionValues = resolvedGroupBy.map((entry) => row[entry.resultKey]);
1024
+ const seriesKey = JSON.stringify(dimensionValues);
1025
+ const name = dimensionValues.map(toSeriesDisplayValue).join("|");
1026
+ const costSummary = normalizeCostSummaryRow(row);
1027
+ if (!seriesMap.has(seriesKey)) {
1028
+ seriesMap.set(seriesKey, {
1029
+ name,
1030
+ costUnits: /* @__PURE__ */ new Set(),
1031
+ points: []
1032
+ });
1033
+ }
1034
+ if (costSummary.costUnit) {
1035
+ seriesMap.get(seriesKey).costUnits.add(costSummary.costUnit);
1036
+ }
1037
+ seriesMap.get(seriesKey).points.push({
1038
+ timestamp: row.bucket instanceof Date ? row.bucket : new Date(String(row.bucket)),
1039
+ value: Number(row.value ?? 0),
1040
+ estimatedCost: costSummary.estimatedCost
1041
+ });
1042
+ }
1043
+ return {
1044
+ series: Array.from(seriesMap.values()).map((series) => ({
1045
+ name: series.name,
1046
+ costUnit: series.costUnits.size === 1 ? Array.from(series.costUnits)[0] : null,
1047
+ points: series.points
1048
+ }))
1049
+ };
1050
+ }
1051
+ const sql = `
1052
+ SELECT time_bucket(INTERVAL '${intervalSql}', timestamp) AS bucket,
1053
+ ${aggSql} AS value,
1054
+ ${getCostSummarySelect()}
1055
+ FROM metric_events ${whereClause}
1056
+ GROUP BY bucket
1057
+ ORDER BY bucket
1058
+ `;
1059
+ const rows = await db.query(sql, allParams);
1060
+ const metricName = Array.isArray(args.name) ? args.name.join(",") : args.name;
1061
+ const overallCostUnits = new Set(
1062
+ rows.map((row) => row.costUnit).filter((value) => typeof value === "string")
1063
+ );
1064
+ return {
1065
+ series: [
1066
+ {
1067
+ name: metricName,
1068
+ costUnit: overallCostUnits.size === 1 ? Array.from(overallCostUnits)[0] : null,
1069
+ points: rows.map((row) => {
1070
+ const costSummary = normalizeCostSummaryRow(row);
1071
+ return {
1072
+ timestamp: row.bucket instanceof Date ? row.bucket : new Date(String(row.bucket)),
1073
+ value: Number(row.value ?? 0),
1074
+ estimatedCost: costSummary.estimatedCost
1075
+ };
1076
+ })
1077
+ }
1078
+ ]
1079
+ };
1080
+ }
1081
+ async function getMetricPercentiles(db, args) {
1082
+ const intervalSql = getIntervalSql(args.interval);
1083
+ const { clause: filterClause, params: filterParams } = buildWhereClause(
1084
+ args.filters
1085
+ );
1086
+ const allConditions = [`name = ?`];
1087
+ const allParams = [args.name];
1088
+ if (filterClause) {
1089
+ allConditions.push(filterClause.replace("WHERE ", ""));
1090
+ allParams.push(...filterParams);
1091
+ }
1092
+ const whereClause = `WHERE ${allConditions.join(" AND ")}`;
1093
+ const series = [];
1094
+ for (const p of args.percentiles) {
1095
+ const sql = `
1096
+ SELECT time_bucket(INTERVAL '${intervalSql}', timestamp) AS bucket,
1097
+ percentile_cont(${p}) WITHIN GROUP (ORDER BY value) AS pvalue
1098
+ FROM metric_events ${whereClause}
1099
+ GROUP BY bucket
1100
+ ORDER BY bucket
1101
+ `;
1102
+ const rows = await db.query(sql, allParams);
1103
+ series.push({
1104
+ percentile: p,
1105
+ points: rows.map((row) => ({
1106
+ timestamp: row.bucket instanceof Date ? row.bucket : new Date(String(row.bucket)),
1107
+ value: Number(row.pvalue ?? 0)
1108
+ }))
1109
+ });
1110
+ }
1111
+ return { series };
1112
+ }
1113
+ async function getMetricNames(db, args) {
1114
+ const conditions = [];
1115
+ const params = [];
1116
+ if (args.prefix) {
1117
+ conditions.push(`name LIKE ?`);
1118
+ params.push(`${args.prefix}%`);
1119
+ }
1120
+ const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
1121
+ const limitClause = args.limit ? `LIMIT ?` : "";
1122
+ if (args.limit) params.push(args.limit);
1123
+ const rows = await db.query(
1124
+ `SELECT DISTINCT name FROM metric_events ${whereClause} ORDER BY name ${limitClause}`,
1125
+ params
1126
+ );
1127
+ return { names: rows.map((r) => r.name) };
1128
+ }
1129
+ async function getMetricLabelKeys(db, args) {
1130
+ const rows = await db.query(
1131
+ `SELECT DISTINCT unnest(json_keys(labels)) AS key FROM metric_events WHERE name = ? AND labels IS NOT NULL`,
1132
+ [args.metricName]
1133
+ );
1134
+ return { keys: rows.map((r) => r.key) };
1135
+ }
1136
+ async function getMetricLabelValues(db, args) {
1137
+ const labelPath = buildJsonPath(args.labelKey);
1138
+ const conditions = [`name = ?`, `json_extract_string(labels, ?) IS NOT NULL`];
1139
+ const params = [args.metricName, labelPath];
1140
+ if (args.prefix) {
1141
+ conditions.push(`json_extract_string(labels, ?) LIKE ?`);
1142
+ params.push(labelPath, `${args.prefix}%`);
1143
+ }
1144
+ const limitClause = args.limit ? `LIMIT ?` : "";
1145
+ if (args.limit) params.push(args.limit);
1146
+ const rows = await db.query(
1147
+ `SELECT DISTINCT json_extract_string(labels, ?) AS val FROM metric_events WHERE ${conditions.join(" AND ")} ORDER BY val ${limitClause}`,
1148
+ [labelPath, ...params]
1149
+ );
1150
+ return { values: rows.map((r) => r.val) };
1151
+ }
1152
+
1153
+ // src/storage/domains/observability/scores.ts
1154
+ async function createScore(db, args) {
1155
+ const s = args.score;
1156
+ await db.execute(
1157
+ `INSERT INTO score_events (timestamp, traceId, spanId, scorerId, scorerVersion, source, score, reason, experimentId, scoreTraceId, metadata)
1158
+ VALUES (${[
1159
+ v(s.timestamp),
1160
+ v(s.traceId),
1161
+ v(s.spanId ?? null),
1162
+ v(s.scorerId),
1163
+ v(s.scorerVersion ?? null),
1164
+ v(s.source ?? null),
1165
+ v(s.score),
1166
+ v(s.reason ?? null),
1167
+ v(s.experimentId ?? null),
1168
+ v(s.scoreTraceId ?? null),
1169
+ jsonV(s.metadata)
1170
+ ].join(", ")})`
1171
+ );
1172
+ }
1173
+ async function batchCreateScores(db, args) {
1174
+ if (args.scores.length === 0) return;
1175
+ const tuples = args.scores.map(
1176
+ (s) => `(${[
1177
+ v(s.timestamp),
1178
+ v(s.traceId),
1179
+ v(s.spanId ?? null),
1180
+ v(s.scorerId),
1181
+ v(s.scorerVersion ?? null),
1182
+ v(s.source ?? null),
1183
+ v(s.score),
1184
+ v(s.reason ?? null),
1185
+ v(s.experimentId ?? null),
1186
+ v(s.scoreTraceId ?? null),
1187
+ jsonV(s.metadata)
1188
+ ].join(", ")})`
1189
+ );
1190
+ await db.execute(
1191
+ `INSERT INTO score_events (timestamp, traceId, spanId, scorerId, scorerVersion, source, score, reason, experimentId, scoreTraceId, metadata)
1192
+ VALUES ${tuples.join(",\n ")}`
1193
+ );
1194
+ }
1195
+ async function listScores(db, args) {
1196
+ const filters = args.filters ?? {};
1197
+ const page = Number(args.pagination?.page ?? 0);
1198
+ const perPage = Number(args.pagination?.perPage ?? 10);
1199
+ const orderBy = { field: args.orderBy?.field ?? "timestamp", direction: args.orderBy?.direction ?? "DESC" };
1200
+ const { clause: filterClause, params: filterParams } = buildWhereClause(filters);
1201
+ const orderByClause = buildOrderByClause(orderBy);
1202
+ const { clause: paginationClause, params: paginationParams } = buildPaginationClause({ page, perPage });
1203
+ const countResult = await db.query(
1204
+ `SELECT COUNT(*) as total FROM score_events ${filterClause}`,
1205
+ filterParams
1206
+ );
1207
+ const total = Number(countResult[0]?.total ?? 0);
1208
+ const rows = await db.query(`SELECT * FROM score_events ${filterClause} ${orderByClause} ${paginationClause}`, [
1209
+ ...filterParams,
1210
+ ...paginationParams
1211
+ ]);
1212
+ const scores = rows.map((row) => {
1213
+ const r = row;
1214
+ return {
1215
+ timestamp: toDate(r.timestamp),
1216
+ traceId: r.traceId,
1217
+ spanId: r.spanId ?? null,
1218
+ scorerId: r.scorerId,
1219
+ scorerVersion: r.scorerVersion ?? null,
1220
+ source: r.source ?? null,
1221
+ score: Number(r.score),
1222
+ reason: r.reason ?? null,
1223
+ experimentId: r.experimentId ?? null,
1224
+ scoreTraceId: r.scoreTraceId ?? null,
1225
+ metadata: parseJson(r.metadata)
1226
+ };
1227
+ });
1228
+ return {
1229
+ pagination: { total, page, perPage, hasMore: (page + 1) * perPage < total },
1230
+ scores
1231
+ };
1232
+ }
1233
+ var COLUMNS2 = [
1234
+ "eventType",
1235
+ "timestamp",
1236
+ "traceId",
1237
+ "spanId",
1238
+ "parentSpanId",
1239
+ "name",
1240
+ "spanType",
1241
+ "isEvent",
1242
+ "endedAt",
1243
+ "experimentId",
1244
+ "entityType",
1245
+ "entityId",
1246
+ "entityName",
1247
+ "userId",
1248
+ "organizationId",
1249
+ "resourceId",
1250
+ "runId",
1251
+ "sessionId",
1252
+ "threadId",
1253
+ "requestId",
1254
+ "environment",
1255
+ "source",
1256
+ "serviceName",
1257
+ "attributes",
1258
+ "metadata",
1259
+ "tags",
1260
+ "scope",
1261
+ "links",
1262
+ "input",
1263
+ "output",
1264
+ "error",
1265
+ "requestContext"
1266
+ ];
1267
+ var COLUMNS_SQL2 = COLUMNS2.join(", ");
1268
+ function argMaxNonNull(col) {
1269
+ return `arg_max(${col}, timestamp) FILTER (WHERE ${col} IS NOT NULL) as ${col}`;
1270
+ }
1271
+ var SPAN_RECONSTRUCT_SELECT = `
1272
+ SELECT
1273
+ traceId, spanId,
1274
+ ${argMaxNonNull("name")},
1275
+ ${argMaxNonNull("spanType")},
1276
+ ${argMaxNonNull("parentSpanId")},
1277
+ ${argMaxNonNull("isEvent")},
1278
+ coalesce(min(timestamp) FILTER (WHERE eventType = 'start'), min(timestamp)) as startedAt,
1279
+ ${argMaxNonNull("endedAt")},
1280
+ ${argMaxNonNull("experimentId")},
1281
+ ${argMaxNonNull("entityType")},
1282
+ ${argMaxNonNull("entityId")},
1283
+ ${argMaxNonNull("entityName")},
1284
+ ${argMaxNonNull("userId")},
1285
+ ${argMaxNonNull("organizationId")},
1286
+ ${argMaxNonNull("resourceId")},
1287
+ ${argMaxNonNull("runId")},
1288
+ ${argMaxNonNull("sessionId")},
1289
+ ${argMaxNonNull("threadId")},
1290
+ ${argMaxNonNull("requestId")},
1291
+ ${argMaxNonNull("environment")},
1292
+ ${argMaxNonNull("source")},
1293
+ ${argMaxNonNull("serviceName")},
1294
+ ${argMaxNonNull("attributes")},
1295
+ ${argMaxNonNull("metadata")},
1296
+ ${argMaxNonNull("tags")},
1297
+ ${argMaxNonNull("scope")},
1298
+ ${argMaxNonNull("links")},
1299
+ ${argMaxNonNull("input")},
1300
+ ${argMaxNonNull("output")},
1301
+ ${argMaxNonNull("error")},
1302
+ ${argMaxNonNull("requestContext")}
1303
+ FROM span_events
1304
+ `;
1305
+ function rowToSpanRecord(row) {
1306
+ return {
1307
+ traceId: row.traceId,
1308
+ spanId: row.spanId,
1309
+ name: row.name,
1310
+ spanType: row.spanType,
1311
+ parentSpanId: row.parentSpanId ?? null,
1312
+ isEvent: row.isEvent,
1313
+ startedAt: toDate(row.startedAt),
1314
+ endedAt: toDateOrNull(row.endedAt),
1315
+ experimentId: row.experimentId ?? null,
1316
+ entityType: row.entityType ?? null,
1317
+ entityId: row.entityId ?? null,
1318
+ entityName: row.entityName ?? null,
1319
+ userId: row.userId ?? null,
1320
+ organizationId: row.organizationId ?? null,
1321
+ resourceId: row.resourceId ?? null,
1322
+ runId: row.runId ?? null,
1323
+ sessionId: row.sessionId ?? null,
1324
+ threadId: row.threadId ?? null,
1325
+ requestId: row.requestId ?? null,
1326
+ environment: row.environment ?? null,
1327
+ source: row.source ?? null,
1328
+ serviceName: row.serviceName ?? null,
1329
+ attributes: parseJson(row.attributes),
1330
+ metadata: parseJson(row.metadata),
1331
+ tags: parseJsonArray(row.tags),
1332
+ scope: parseJson(row.scope),
1333
+ links: parseJsonArray(row.links),
1334
+ input: parseJson(row.input),
1335
+ output: parseJson(row.output),
1336
+ error: parseJson(row.error),
1337
+ requestContext: parseJson(row.requestContext),
1338
+ createdAt: toDate(row.startedAt),
1339
+ updatedAt: null
1340
+ };
1341
+ }
1342
+ function buildHasChildErrorClause(hasChildError) {
1343
+ if (hasChildError === void 0) return "";
1344
+ const base = `SELECT 1 FROM reconstructed_spans c WHERE c.traceId = root_spans.traceId AND c.spanId != root_spans.spanId AND c.error IS NOT NULL`;
1345
+ return hasChildError ? `EXISTS (${base})` : `NOT EXISTS (${base})`;
1346
+ }
1347
+ function toValuesTuple(row) {
1348
+ return [
1349
+ v(row.eventType),
1350
+ v(row.timestamp),
1351
+ v(row.traceId),
1352
+ v(row.spanId),
1353
+ v(row.parentSpanId),
1354
+ v(row.name),
1355
+ v(row.spanType),
1356
+ v(row.isEvent),
1357
+ v(row.endedAt),
1358
+ v(row.experimentId),
1359
+ v(row.entityType),
1360
+ v(row.entityId),
1361
+ v(row.entityName),
1362
+ v(row.userId),
1363
+ v(row.organizationId),
1364
+ v(row.resourceId),
1365
+ v(row.runId),
1366
+ v(row.sessionId),
1367
+ v(row.threadId),
1368
+ v(row.requestId),
1369
+ v(row.environment),
1370
+ v(row.source),
1371
+ v(row.serviceName),
1372
+ jsonV(row.attributes),
1373
+ jsonV(row.metadata),
1374
+ jsonV(row.tags),
1375
+ jsonV(row.scope),
1376
+ jsonV(row.links),
1377
+ jsonV(row.input),
1378
+ jsonV(row.output),
1379
+ jsonV(row.error),
1380
+ jsonV(row.requestContext)
1381
+ ].join(", ");
1382
+ }
1383
+ async function insertSpanEvents(db, rows) {
1384
+ if (rows.length === 0) return;
1385
+ const tuples = rows.map((row) => `(${toValuesTuple(row)})`).join(",\n");
1386
+ await db.execute(`INSERT INTO span_events (${COLUMNS_SQL2}) VALUES ${tuples}`);
1387
+ }
1388
+ function createStartSpanRow(s) {
1389
+ return {
1390
+ eventType: "start",
1391
+ timestamp: s.startedAt,
1392
+ traceId: s.traceId,
1393
+ spanId: s.spanId,
1394
+ parentSpanId: s.parentSpanId ?? null,
1395
+ name: s.name,
1396
+ spanType: s.spanType,
1397
+ isEvent: s.isEvent,
1398
+ endedAt: null,
1399
+ experimentId: s.experimentId ?? null,
1400
+ entityType: s.entityType ?? null,
1401
+ entityId: s.entityId ?? null,
1402
+ entityName: s.entityName ?? null,
1403
+ userId: s.userId ?? null,
1404
+ organizationId: s.organizationId ?? null,
1405
+ resourceId: s.resourceId ?? null,
1406
+ runId: s.runId ?? null,
1407
+ sessionId: s.sessionId ?? null,
1408
+ threadId: s.threadId ?? null,
1409
+ requestId: s.requestId ?? null,
1410
+ environment: s.environment ?? null,
1411
+ source: s.source ?? null,
1412
+ serviceName: s.serviceName ?? null,
1413
+ attributes: s.attributes ?? null,
1414
+ metadata: s.metadata ?? null,
1415
+ tags: s.tags ?? null,
1416
+ scope: s.scope ?? null,
1417
+ links: null,
1418
+ input: s.input ?? null,
1419
+ output: null,
1420
+ error: null,
1421
+ requestContext: s.requestContext ?? null
1422
+ };
1423
+ }
1424
+ function createEndSpanRow(s) {
1425
+ return {
1426
+ eventType: "end",
1427
+ timestamp: s.endedAt,
1428
+ traceId: s.traceId,
1429
+ spanId: s.spanId,
1430
+ parentSpanId: s.parentSpanId ?? null,
1431
+ name: s.name,
1432
+ spanType: s.spanType,
1433
+ isEvent: s.isEvent,
1434
+ endedAt: s.endedAt ?? null,
1435
+ experimentId: s.experimentId ?? null,
1436
+ entityType: s.entityType ?? null,
1437
+ entityId: s.entityId ?? null,
1438
+ entityName: s.entityName ?? null,
1439
+ userId: s.userId ?? null,
1440
+ organizationId: s.organizationId ?? null,
1441
+ resourceId: s.resourceId ?? null,
1442
+ runId: s.runId ?? null,
1443
+ sessionId: s.sessionId ?? null,
1444
+ threadId: s.threadId ?? null,
1445
+ requestId: s.requestId ?? null,
1446
+ environment: s.environment ?? null,
1447
+ source: s.source ?? null,
1448
+ serviceName: s.serviceName ?? null,
1449
+ attributes: s.attributes ?? null,
1450
+ metadata: s.metadata ?? null,
1451
+ tags: s.tags ?? null,
1452
+ scope: s.scope ?? null,
1453
+ links: s.links ?? null,
1454
+ input: s.input ?? null,
1455
+ output: s.output ?? null,
1456
+ error: s.error ?? null,
1457
+ requestContext: s.requestContext ?? null
1458
+ };
1459
+ }
1460
+ async function createSpan(db, args) {
1461
+ const rows = [createStartSpanRow(args.span)];
1462
+ if (args.span.endedAt) {
1463
+ rows.push(createEndSpanRow(args.span));
1464
+ }
1465
+ await insertSpanEvents(db, rows);
1466
+ }
1467
+ async function batchCreateSpans(db, args) {
1468
+ if (args.records.length === 0) return;
1469
+ const rows = args.records.flatMap((record) => {
1470
+ const events = [createStartSpanRow(record)];
1471
+ if (record.endedAt) {
1472
+ events.push(createEndSpanRow(record));
1473
+ }
1474
+ return events;
1475
+ });
1476
+ await insertSpanEvents(db, rows);
1477
+ }
1478
+ async function batchDeleteTraces(db, args) {
1479
+ if (args.traceIds.length === 0) return;
1480
+ const placeholders = args.traceIds.map(() => "?").join(", ");
1481
+ await db.execute(`DELETE FROM span_events WHERE traceId IN (${placeholders})`, args.traceIds);
1482
+ }
1483
+ async function getSpan(db, args) {
1484
+ const rows = await db.query(`${SPAN_RECONSTRUCT_SELECT} WHERE traceId = ? AND spanId = ? GROUP BY traceId, spanId`, [
1485
+ args.traceId,
1486
+ args.spanId
1487
+ ]);
1488
+ if (rows.length === 0) return null;
1489
+ return { span: rowToSpanRecord(rows[0]) };
1490
+ }
1491
+ async function getRootSpan(db, args) {
1492
+ const rows = await db.query(
1493
+ `${SPAN_RECONSTRUCT_SELECT} WHERE traceId = ? GROUP BY traceId, spanId HAVING arg_max(parentSpanId, timestamp) IS NULL LIMIT 1`,
1494
+ [args.traceId]
1495
+ );
1496
+ if (rows.length === 0) return null;
1497
+ return { span: rowToSpanRecord(rows[0]) };
1498
+ }
1499
+ async function getTrace(db, args) {
1500
+ const rows = await db.query(`${SPAN_RECONSTRUCT_SELECT} WHERE traceId = ? GROUP BY traceId, spanId`, [args.traceId]);
1501
+ if (rows.length === 0) return null;
1502
+ return {
1503
+ traceId: args.traceId,
1504
+ spans: rows.map((row) => rowToSpanRecord(row))
1505
+ };
1506
+ }
1507
+ async function listTraces(db, args) {
1508
+ const filters = args.filters ?? {};
1509
+ const page = Number(args.pagination?.page ?? 0);
1510
+ const perPage = Number(args.pagination?.perPage ?? 10);
1511
+ const orderBy = { field: args.orderBy?.field ?? "startedAt", direction: args.orderBy?.direction ?? "DESC" };
1512
+ const { clause: filterClause, params: filterParams } = buildWhereClause(filters);
1513
+ const orderByClause = buildOrderByClause(orderBy);
1514
+ const { clause: paginationClause, params: paginationParams } = buildPaginationClause({ page, perPage });
1515
+ const filterParts = [];
1516
+ if (filterClause) filterParts.push(filterClause.replace(/^WHERE\s+/i, ""));
1517
+ const hasChildError = typeof filters.hasChildError === "boolean" ? filters.hasChildError : void 0;
1518
+ const childErrorClause = buildHasChildErrorClause(hasChildError);
1519
+ if (childErrorClause) filterParts.push(childErrorClause);
1520
+ const combinedFilterClause = filterParts.length > 0 ? `WHERE ${filterParts.join(" AND ")}` : "";
1521
+ const cteSql = `
1522
+ WITH reconstructed_spans AS (
1523
+ ${SPAN_RECONSTRUCT_SELECT}
1524
+ GROUP BY traceId, spanId
1525
+ ),
1526
+ root_spans AS (
1527
+ SELECT * FROM reconstructed_spans
1528
+ WHERE parentSpanId IS NULL
1529
+ )
1530
+ `;
1531
+ const countSql = `
1532
+ ${cteSql}
1533
+ SELECT COUNT(*) as total FROM root_spans ${combinedFilterClause}
1534
+ `;
1535
+ const countResult = await db.query(countSql, filterParams);
1536
+ const total = Number(countResult[0]?.total ?? 0);
1537
+ const dataSql = `
1538
+ ${cteSql}
1539
+ SELECT * FROM root_spans ${combinedFilterClause} ${orderByClause} ${paginationClause}
1540
+ `;
1541
+ const rows = await db.query(dataSql, [...filterParams, ...paginationParams]);
1542
+ const spans = rows.map((row) => rowToSpanRecord(row));
1543
+ return {
1544
+ pagination: {
1545
+ total,
1546
+ page,
1547
+ perPage,
1548
+ hasMore: (page + 1) * perPage < total
1549
+ },
1550
+ spans: storage.toTraceSpans(spans)
1551
+ };
1552
+ }
1553
+
1554
+ // src/storage/domains/observability/index.ts
1555
+ var ObservabilityStorageDuckDB = class extends storage.ObservabilityStorage {
1556
+ db;
1557
+ constructor(config) {
1558
+ super();
1559
+ this.db = config.db;
1560
+ }
1561
+ /** Create all observability tables if they don't exist. */
1562
+ async init() {
1563
+ for (const ddl of ALL_DDL) {
1564
+ await this.db.execute(ddl);
1565
+ }
1566
+ }
1567
+ /** Delete all rows from every observability table. Use with caution. */
1568
+ async dangerouslyClearAll() {
1569
+ for (const table of ["span_events", "metric_events", "log_events", "score_events", "feedback_events"]) {
1570
+ await this.db.execute(`TRUNCATE TABLE ${table}`);
1571
+ }
1572
+ }
1573
+ get observabilityStrategy() {
1574
+ return {
1575
+ preferred: "event-sourced",
1576
+ supported: ["event-sourced"]
1577
+ };
1578
+ }
1579
+ // Tracing
1580
+ async createSpan(args) {
1581
+ return createSpan(this.db, args);
1582
+ }
1583
+ async batchCreateSpans(args) {
1584
+ return batchCreateSpans(this.db, args);
1585
+ }
1586
+ async batchDeleteTraces(args) {
1587
+ return batchDeleteTraces(this.db, args);
1588
+ }
1589
+ async getSpan(args) {
1590
+ return getSpan(this.db, args);
1591
+ }
1592
+ async getRootSpan(args) {
1593
+ return getRootSpan(this.db, args);
1594
+ }
1595
+ async getTrace(args) {
1596
+ return getTrace(this.db, args);
1597
+ }
1598
+ async listTraces(args) {
1599
+ return listTraces(this.db, args);
1600
+ }
1601
+ // Logs
1602
+ async batchCreateLogs(args) {
1603
+ return batchCreateLogs(this.db, args);
1604
+ }
1605
+ async listLogs(args) {
1606
+ return listLogs(this.db, args);
1607
+ }
1608
+ // Metrics
1609
+ async batchCreateMetrics(args) {
1610
+ return batchCreateMetrics(this.db, args);
1611
+ }
1612
+ async listMetrics(args) {
1613
+ return listMetrics(this.db, args);
1614
+ }
1615
+ async getMetricAggregate(args) {
1616
+ return getMetricAggregate(this.db, args);
1617
+ }
1618
+ async getMetricBreakdown(args) {
1619
+ return getMetricBreakdown(this.db, args);
1620
+ }
1621
+ async getMetricTimeSeries(args) {
1622
+ return getMetricTimeSeries(this.db, args);
1623
+ }
1624
+ async getMetricPercentiles(args) {
1625
+ return getMetricPercentiles(this.db, args);
1626
+ }
1627
+ // Metric Discovery
1628
+ async getMetricNames(args) {
1629
+ return getMetricNames(this.db, args);
1630
+ }
1631
+ async getMetricLabelKeys(args) {
1632
+ return getMetricLabelKeys(this.db, args);
1633
+ }
1634
+ async getMetricLabelValues(args) {
1635
+ return getMetricLabelValues(this.db, args);
1636
+ }
1637
+ // Span Discovery
1638
+ async getEntityTypes(args) {
1639
+ return getEntityTypes(this.db);
1640
+ }
1641
+ async getEntityNames(args) {
1642
+ return getEntityNames(this.db, args);
1643
+ }
1644
+ async getServiceNames(args) {
1645
+ return getServiceNames(this.db);
1646
+ }
1647
+ async getEnvironments(args) {
1648
+ return getEnvironments(this.db);
1649
+ }
1650
+ async getTags(args) {
1651
+ return getTags(this.db, args);
1652
+ }
1653
+ // Scores
1654
+ async createScore(args) {
1655
+ return createScore(this.db, args);
1656
+ }
1657
+ async batchCreateScores(args) {
1658
+ return batchCreateScores(this.db, args);
1659
+ }
1660
+ async listScores(args) {
1661
+ return listScores(this.db, args);
1662
+ }
1663
+ // Feedback
1664
+ async createFeedback(args) {
1665
+ return createFeedback(this.db, args);
1666
+ }
1667
+ async batchCreateFeedback(args) {
1668
+ return batchCreateFeedback(this.db, args);
1669
+ }
1670
+ async listFeedback(args) {
1671
+ return listFeedback(this.db, args);
1672
+ }
1673
+ };
1674
+
1675
+ exports.ObservabilityStorageDuckDB = ObservabilityStorageDuckDB;
1676
+ //# sourceMappingURL=observability-W2QRBK56.cjs.map
1677
+ //# sourceMappingURL=observability-W2QRBK56.cjs.map