@mastra/duckdb 1.8.0 → 1.9.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.
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/index.cjs +8 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +8 -3
- package/dist/index.js.map +1 -1
- package/dist/{observability-BZcL6fKR.cjs → observability-BB4mjnZR.cjs} +142 -27
- package/dist/observability-BB4mjnZR.cjs.map +1 -0
- package/dist/{observability-COgD6BOK.js → observability-DEjVUB3O.js} +142 -27
- package/dist/observability-DEjVUB3O.js.map +1 -0
- package/dist/storage/domains/observability/ddl.d.ts +1 -1
- package/dist/storage/domains/observability/ddl.d.ts.map +1 -1
- package/dist/storage/domains/observability/feedback.d.ts.map +1 -1
- package/dist/storage/domains/observability/index.d.ts +3 -2
- package/dist/storage/domains/observability/index.d.ts.map +1 -1
- package/dist/storage/domains/observability/trace-query.d.ts +3 -1
- package/dist/storage/domains/observability/trace-query.d.ts.map +1 -1
- package/dist/storage/index.d.ts +1 -0
- package/dist/storage/index.d.ts.map +1 -1
- package/package.json +5 -5
- package/dist/observability-BZcL6fKR.cjs.map +0 -1
- package/dist/observability-COgD6BOK.js.map +0 -1
|
@@ -290,6 +290,8 @@ CREATE TABLE IF NOT EXISTS feedback_events (
|
|
|
290
290
|
feedbackSource VARCHAR NOT NULL,
|
|
291
291
|
feedbackType VARCHAR NOT NULL,
|
|
292
292
|
value VARCHAR NOT NULL,
|
|
293
|
+
valueString VARCHAR,
|
|
294
|
+
valueNumber DOUBLE,
|
|
293
295
|
comment VARCHAR,
|
|
294
296
|
|
|
295
297
|
-- JSON fields
|
|
@@ -425,6 +427,8 @@ const ALL_MIGRATIONS = [
|
|
|
425
427
|
`ALTER TABLE feedback_events ADD COLUMN IF NOT EXISTS scope JSON`,
|
|
426
428
|
`ALTER TABLE feedback_events ADD COLUMN IF NOT EXISTS source VARCHAR`,
|
|
427
429
|
`ALTER TABLE feedback_events ADD COLUMN IF NOT EXISTS feedbackSource VARCHAR`,
|
|
430
|
+
`ALTER TABLE feedback_events ADD COLUMN IF NOT EXISTS valueString VARCHAR`,
|
|
431
|
+
`ALTER TABLE feedback_events ADD COLUMN IF NOT EXISTS valueNumber DOUBLE`,
|
|
428
432
|
`ALTER TABLE feedback_events ADD COLUMN IF NOT EXISTS reviewStatus VARCHAR DEFAULT 'needs-review'`,
|
|
429
433
|
`ALTER TABLE feedback_events ALTER COLUMN traceId DROP NOT NULL`
|
|
430
434
|
];
|
|
@@ -779,6 +783,8 @@ const FEEDBACK_UPSERT_CLAUSE = `ON CONFLICT (feedbackId) DO UPDATE SET ${[
|
|
|
779
783
|
"feedbackSource",
|
|
780
784
|
"feedbackType",
|
|
781
785
|
"value",
|
|
786
|
+
"valueString",
|
|
787
|
+
"valueNumber",
|
|
782
788
|
"comment",
|
|
783
789
|
"tags",
|
|
784
790
|
"metadata",
|
|
@@ -818,7 +824,7 @@ const FEEDBACK_GROUP_BY_COLUMNS = /* @__PURE__ */ new Set([
|
|
|
818
824
|
"value",
|
|
819
825
|
"comment"
|
|
820
826
|
]);
|
|
821
|
-
function getAggregationSql$2(aggregation, measure = "
|
|
827
|
+
function getAggregationSql$2(aggregation, measure = "valueNumber") {
|
|
822
828
|
switch (aggregation) {
|
|
823
829
|
case "sum": return `SUM(${measure})`;
|
|
824
830
|
case "avg": return `AVG(${measure})`;
|
|
@@ -858,7 +864,7 @@ function buildFeedbackWhereClause(args, includeNumericGuard = false) {
|
|
|
858
864
|
conditions.push(filterClause.replace("WHERE ", ""));
|
|
859
865
|
params.push(...filterParams);
|
|
860
866
|
}
|
|
861
|
-
if (includeNumericGuard) conditions.push("
|
|
867
|
+
if (includeNumericGuard) conditions.push("valueNumber IS NOT NULL");
|
|
862
868
|
return {
|
|
863
869
|
clause: `WHERE ${conditions.join(" AND ")}`,
|
|
864
870
|
params
|
|
@@ -879,11 +885,12 @@ function resolveFeedbackGroupBy(groupBy) {
|
|
|
879
885
|
function toSeriesName$1(values) {
|
|
880
886
|
return values.map((value) => value === null || value === void 0 ? "" : String(value)).join("|");
|
|
881
887
|
}
|
|
888
|
+
function readFeedbackValue(row) {
|
|
889
|
+
if (row.valueNumber != null) return Number(row.valueNumber);
|
|
890
|
+
if (row.valueString != null) return String(row.valueString);
|
|
891
|
+
return String(row.value);
|
|
892
|
+
}
|
|
882
893
|
function rowToFeedbackRecord(row) {
|
|
883
|
-
const rawValue = row.value;
|
|
884
|
-
let value = rawValue;
|
|
885
|
-
const numValue = Number(rawValue);
|
|
886
|
-
if (!isNaN(numValue)) value = numValue;
|
|
887
894
|
return feedbackRecordSchema.parse({
|
|
888
895
|
feedbackId: row.feedbackId,
|
|
889
896
|
timestamp: toDate(row.timestamp),
|
|
@@ -918,7 +925,7 @@ function rowToFeedbackRecord(row) {
|
|
|
918
925
|
source: row.feedbackSource,
|
|
919
926
|
feedbackSource: row.feedbackSource,
|
|
920
927
|
feedbackType: row.feedbackType,
|
|
921
|
-
value,
|
|
928
|
+
value: readFeedbackValue(row),
|
|
922
929
|
comment: row.comment ?? null,
|
|
923
930
|
tags: parseJsonArray(row.tags),
|
|
924
931
|
metadata: parseJson(row.metadata),
|
|
@@ -958,7 +965,7 @@ async function createFeedback(db, args) {
|
|
|
958
965
|
feedbackId, timestamp, cursorId, traceId, spanId, experimentId,
|
|
959
966
|
entityType, entityId, entityName, entityVersionId, parentEntityVersionId, parentEntityType, parentEntityId, parentEntityName, rootEntityVersionId, rootEntityType, rootEntityId, rootEntityName,
|
|
960
967
|
userId, organizationId, resourceId, runId, sessionId, threadId, requestId, environment, executionSource, serviceName,
|
|
961
|
-
feedbackUserId, sourceId, reviewStatus, feedbackSource, feedbackType, value, comment, tags, metadata, scope
|
|
968
|
+
feedbackUserId, sourceId, reviewStatus, feedbackSource, feedbackType, value, valueString, valueNumber, comment, tags, metadata, scope
|
|
962
969
|
)
|
|
963
970
|
VALUES (${[
|
|
964
971
|
v(f.feedbackId),
|
|
@@ -995,6 +1002,8 @@ async function createFeedback(db, args) {
|
|
|
995
1002
|
v(feedbackSource),
|
|
996
1003
|
v(f.feedbackType),
|
|
997
1004
|
v(String(f.value)),
|
|
1005
|
+
v(typeof f.value === "string" ? f.value : null),
|
|
1006
|
+
v(typeof f.value === "number" ? f.value : null),
|
|
998
1007
|
v(f.comment ?? null),
|
|
999
1008
|
jsonV(f.tags ?? null),
|
|
1000
1009
|
jsonV(f.metadata),
|
|
@@ -1044,6 +1053,8 @@ async function batchCreateFeedback(db, args) {
|
|
|
1044
1053
|
v(feedbackSource),
|
|
1045
1054
|
v(legacyFeedback.feedbackType),
|
|
1046
1055
|
v(String(legacyFeedback.value)),
|
|
1056
|
+
v(typeof legacyFeedback.value === "string" ? legacyFeedback.value : null),
|
|
1057
|
+
v(typeof legacyFeedback.value === "number" ? legacyFeedback.value : null),
|
|
1047
1058
|
v(legacyFeedback.comment ?? null),
|
|
1048
1059
|
jsonV(legacyFeedback.tags ?? null),
|
|
1049
1060
|
jsonV(legacyFeedback.metadata),
|
|
@@ -1054,7 +1065,7 @@ async function batchCreateFeedback(db, args) {
|
|
|
1054
1065
|
feedbackId, timestamp, cursorId, traceId, spanId, experimentId,
|
|
1055
1066
|
entityType, entityId, entityName, entityVersionId, parentEntityVersionId, parentEntityType, parentEntityId, parentEntityName, rootEntityVersionId, rootEntityType, rootEntityId, rootEntityName,
|
|
1056
1067
|
userId, organizationId, resourceId, runId, sessionId, threadId, requestId, environment, executionSource, serviceName,
|
|
1057
|
-
feedbackUserId, sourceId, reviewStatus, feedbackSource, feedbackType, value, comment, tags, metadata, scope
|
|
1068
|
+
feedbackUserId, sourceId, reviewStatus, feedbackSource, feedbackType, value, valueString, valueNumber, comment, tags, metadata, scope
|
|
1058
1069
|
)
|
|
1059
1070
|
VALUES ${tuples.join(",\n ")}
|
|
1060
1071
|
${FEEDBACK_UPSERT_CLAUSE}`);
|
|
@@ -1251,7 +1262,7 @@ async function getFeedbackPercentiles(db, args) {
|
|
|
1251
1262
|
for (const percentile of percentiles) {
|
|
1252
1263
|
const rows = await db.query(`
|
|
1253
1264
|
SELECT time_bucket(INTERVAL '${intervalSql}', timestamp) AS bucket,
|
|
1254
|
-
percentile_cont(${percentile}) WITHIN GROUP (ORDER BY
|
|
1265
|
+
percentile_cont(${percentile}) WITHIN GROUP (ORDER BY valueNumber) AS pvalue
|
|
1255
1266
|
FROM feedback_events ${clause}
|
|
1256
1267
|
GROUP BY bucket
|
|
1257
1268
|
ORDER BY bucket
|
|
@@ -2943,7 +2954,7 @@ function compileFeedbackScalarPredicate(predicate) {
|
|
|
2943
2954
|
values: []
|
|
2944
2955
|
};
|
|
2945
2956
|
return compileScalarPredicate(predicate, { value: {
|
|
2946
|
-
sql: typeof (predicate.type === "membership" ? predicate.values[0] : predicate.value) === "number" ? "
|
|
2957
|
+
sql: typeof (predicate.type === "membership" ? predicate.values[0] : predicate.value) === "number" ? "s.valueNumber" : "s.valueString",
|
|
2947
2958
|
parameterType: "scalar"
|
|
2948
2959
|
} });
|
|
2949
2960
|
}
|
|
@@ -2981,6 +2992,36 @@ function compilePredicate(predicate) {
|
|
|
2981
2992
|
}
|
|
2982
2993
|
return compileScalarPredicate(predicate, TRACE_FIELDS, true);
|
|
2983
2994
|
}
|
|
2995
|
+
function compileThreadPredicate(predicate) {
|
|
2996
|
+
if (predicate.type === "relation") {
|
|
2997
|
+
const compiled = compilePredicate(predicate.predicate);
|
|
2998
|
+
const existence = `EXISTS (
|
|
2999
|
+
SELECT 1 FROM eligible_roots r
|
|
3000
|
+
WHERE r.threadId = t.threadId
|
|
3001
|
+
AND (${compiled.sql})
|
|
3002
|
+
)`;
|
|
3003
|
+
return {
|
|
3004
|
+
sql: predicate.quantifier === "some" ? existence : `NOT ${existence}`,
|
|
3005
|
+
values: compiled.values
|
|
3006
|
+
};
|
|
3007
|
+
}
|
|
3008
|
+
if (predicate.type === "boolean") {
|
|
3009
|
+
const values = [];
|
|
3010
|
+
return {
|
|
3011
|
+
sql: predicate.args.map((arg) => {
|
|
3012
|
+
const compiled = compileThreadPredicate(arg);
|
|
3013
|
+
values.push(...compiled.values);
|
|
3014
|
+
return `(${compiled.sql})`;
|
|
3015
|
+
}).join(predicate.operator === "and" ? " AND " : " OR "),
|
|
3016
|
+
values
|
|
3017
|
+
};
|
|
3018
|
+
}
|
|
3019
|
+
const compiled = compileThreadPredicate(predicate.arg);
|
|
3020
|
+
return {
|
|
3021
|
+
sql: `NOT (${compiled.sql})`,
|
|
3022
|
+
values: compiled.values
|
|
3023
|
+
};
|
|
3024
|
+
}
|
|
2984
3025
|
function collectRelatedCollections(predicate, collections = /* @__PURE__ */ new Set()) {
|
|
2985
3026
|
if (!predicate) return collections;
|
|
2986
3027
|
if (predicate.type === "relation") collections.add(predicate.collection);
|
|
@@ -2988,19 +3029,14 @@ function collectRelatedCollections(predicate, collections = /* @__PURE__ */ new
|
|
|
2988
3029
|
else if (predicate.type === "not") collectRelatedCollections(predicate.arg, collections);
|
|
2989
3030
|
return collections;
|
|
2990
3031
|
}
|
|
2991
|
-
function
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
const predicate = compilePredicate(plan.where);
|
|
3000
|
-
conditions.push(`(${predicate.sql})`);
|
|
3001
|
-
values.push(...predicate.values);
|
|
3002
|
-
}
|
|
3003
|
-
const relatedCollections = collectRelatedCollections(plan.where);
|
|
3032
|
+
function collectThreadRelatedCollections(predicate, collections) {
|
|
3033
|
+
if (!predicate) return collections;
|
|
3034
|
+
if (predicate.type === "relation") collectRelatedCollections(predicate.predicate, collections);
|
|
3035
|
+
else if (predicate.type === "boolean") for (const arg of predicate.args) collectThreadRelatedCollections(arg, collections);
|
|
3036
|
+
else collectThreadRelatedCollections(predicate.arg, collections);
|
|
3037
|
+
return collections;
|
|
3038
|
+
}
|
|
3039
|
+
function compileDuckDBTraceScope(relatedCollections) {
|
|
3004
3040
|
const ctes = [
|
|
3005
3041
|
`root_events AS (
|
|
3006
3042
|
SELECT
|
|
@@ -3077,6 +3113,21 @@ function compileDuckDBTraceQuery(plan) {
|
|
|
3077
3113
|
FROM feedback_events f
|
|
3078
3114
|
INNER JOIN root_scope roots ON roots.traceId = f.traceId
|
|
3079
3115
|
)`);
|
|
3116
|
+
return ctes;
|
|
3117
|
+
}
|
|
3118
|
+
function compileDuckDBTraceQuery(plan) {
|
|
3119
|
+
const values = [plan.timeRange.from, plan.timeRange.to];
|
|
3120
|
+
const conditions = [
|
|
3121
|
+
`r.endedAt IS NOT NULL`,
|
|
3122
|
+
`r.startedAt >= CAST(? AS TIMESTAMP)`,
|
|
3123
|
+
`r.startedAt < CAST(? AS TIMESTAMP)`
|
|
3124
|
+
];
|
|
3125
|
+
if (plan.where) {
|
|
3126
|
+
const predicate = compilePredicate(plan.where);
|
|
3127
|
+
conditions.push(`(${predicate.sql})`);
|
|
3128
|
+
values.push(...predicate.values);
|
|
3129
|
+
}
|
|
3130
|
+
const ctes = compileDuckDBTraceScope(collectRelatedCollections(plan.where));
|
|
3080
3131
|
ctes.push(`candidates AS (
|
|
3081
3132
|
SELECT ${TRACE_SELECT}
|
|
3082
3133
|
FROM root_scope r
|
|
@@ -3116,6 +3167,52 @@ LIMIT ?`,
|
|
|
3116
3167
|
values
|
|
3117
3168
|
};
|
|
3118
3169
|
}
|
|
3170
|
+
function compileDuckDBThreadQuery(plan) {
|
|
3171
|
+
const values = [plan.traces.timeRange.from, plan.traces.timeRange.to];
|
|
3172
|
+
const relatedCollections = collectRelatedCollections(plan.traces.where);
|
|
3173
|
+
collectThreadRelatedCollections(plan.where, relatedCollections);
|
|
3174
|
+
const ctes = compileDuckDBTraceScope(relatedCollections);
|
|
3175
|
+
let eligibilitySql = "TRUE";
|
|
3176
|
+
if (plan.traces.where) {
|
|
3177
|
+
const eligibility = compilePredicate(plan.traces.where);
|
|
3178
|
+
eligibilitySql = eligibility.sql;
|
|
3179
|
+
values.push(...eligibility.values);
|
|
3180
|
+
}
|
|
3181
|
+
ctes.push(`eligible_roots AS (
|
|
3182
|
+
SELECT *
|
|
3183
|
+
FROM root_scope r
|
|
3184
|
+
WHERE ${eligibilitySql}
|
|
3185
|
+
)`);
|
|
3186
|
+
ctes.push(`thread_ids AS (
|
|
3187
|
+
SELECT threadId
|
|
3188
|
+
FROM eligible_roots
|
|
3189
|
+
WHERE threadId IS NOT NULL
|
|
3190
|
+
GROUP BY threadId
|
|
3191
|
+
)`);
|
|
3192
|
+
let threadPredicateSql = "TRUE";
|
|
3193
|
+
if (plan.where) {
|
|
3194
|
+
const predicate = compileThreadPredicate(plan.where);
|
|
3195
|
+
threadPredicateSql = predicate.sql;
|
|
3196
|
+
values.push(...predicate.values);
|
|
3197
|
+
}
|
|
3198
|
+
ctes.push(`qualified_threads AS (
|
|
3199
|
+
SELECT t.threadId
|
|
3200
|
+
FROM thread_ids t
|
|
3201
|
+
WHERE ${threadPredicateSql}
|
|
3202
|
+
)`);
|
|
3203
|
+
const pageCondition = plan.cursor ? `WHERE threadId > ?` : "";
|
|
3204
|
+
if (plan.cursor) values.push(plan.cursor.threadId);
|
|
3205
|
+
values.push(plan.limit + 1);
|
|
3206
|
+
return {
|
|
3207
|
+
sql: `WITH ${ctes.join(",\n ")}
|
|
3208
|
+
SELECT threadId
|
|
3209
|
+
FROM qualified_threads
|
|
3210
|
+
${pageCondition}
|
|
3211
|
+
ORDER BY threadId ASC
|
|
3212
|
+
LIMIT ?`,
|
|
3213
|
+
values
|
|
3214
|
+
};
|
|
3215
|
+
}
|
|
3119
3216
|
function asIsoTimestamp(value) {
|
|
3120
3217
|
return value instanceof Date ? value.toISOString() : new Date(value).toISOString();
|
|
3121
3218
|
}
|
|
@@ -3156,6 +3253,19 @@ async function queryTraces(db, plan) {
|
|
|
3156
3253
|
}) : null }
|
|
3157
3254
|
});
|
|
3158
3255
|
}
|
|
3256
|
+
async function queryThreads(db, plan) {
|
|
3257
|
+
const query = compileDuckDBThreadQuery(plan);
|
|
3258
|
+
const rows = await db.query(query.sql, query.values);
|
|
3259
|
+
const threads = rows.slice(0, plan.limit).map((row) => ({ threadId: String(row.threadId) }));
|
|
3260
|
+
const last = threads.at(-1);
|
|
3261
|
+
return coreStorage.queryThreadsResultSchema.parse({
|
|
3262
|
+
threads,
|
|
3263
|
+
page: { next: rows.length > plan.limit && last ? coreStorage.encodeTraceQueryCursor(plan, {
|
|
3264
|
+
result: "threads",
|
|
3265
|
+
threadId: last.threadId
|
|
3266
|
+
}) : null }
|
|
3267
|
+
});
|
|
3268
|
+
}
|
|
3159
3269
|
//#endregion
|
|
3160
3270
|
//#region src/storage/domains/observability/tracing.ts
|
|
3161
3271
|
const COLUMNS_SQL = [
|
|
@@ -4395,13 +4505,15 @@ var ObservabilityStorageDuckDB = class extends ObservabilityStorage {
|
|
|
4395
4505
|
if (!deltaPollingFeatureEnabled()) return [
|
|
4396
4506
|
"metrics",
|
|
4397
4507
|
"logs",
|
|
4398
|
-
"trace-query"
|
|
4508
|
+
"trace-query",
|
|
4509
|
+
"thread-query"
|
|
4399
4510
|
];
|
|
4400
4511
|
return [
|
|
4401
4512
|
"metrics",
|
|
4402
4513
|
"logs",
|
|
4403
4514
|
"delta-polling",
|
|
4404
|
-
"trace-query"
|
|
4515
|
+
"trace-query",
|
|
4516
|
+
"thread-query"
|
|
4405
4517
|
];
|
|
4406
4518
|
}
|
|
4407
4519
|
async createSpan(args) {
|
|
@@ -4434,6 +4546,9 @@ var ObservabilityStorageDuckDB = class extends ObservabilityStorage {
|
|
|
4434
4546
|
async queryTraces(plan) {
|
|
4435
4547
|
return queryTraces(this.db, plan);
|
|
4436
4548
|
}
|
|
4549
|
+
async queryThreads(plan) {
|
|
4550
|
+
return queryThreads(this.db, plan);
|
|
4551
|
+
}
|
|
4437
4552
|
async listTracesLight(args) {
|
|
4438
4553
|
if (args.mode === "delta") return super.listTracesLight(args);
|
|
4439
4554
|
return listTracesLight(this.db, args);
|
|
@@ -4547,4 +4662,4 @@ var ObservabilityStorageDuckDB = class extends ObservabilityStorage {
|
|
|
4547
4662
|
//#endregion
|
|
4548
4663
|
export { ObservabilityStorageDuckDB };
|
|
4549
4664
|
|
|
4550
|
-
//# sourceMappingURL=observability-
|
|
4665
|
+
//# sourceMappingURL=observability-DEjVUB3O.js.map
|