@mastra/duckdb 1.16.0 → 1.17.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/README.md +1 -1
- package/dist/docs/SKILL.md +2 -2
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/integrations-databases-duckdb.md +2 -2
- package/dist/{features-DH60yLCA.cjs → features-CBdrOdEO.cjs} +98 -9
- package/dist/features-CBdrOdEO.cjs.map +1 -0
- package/dist/{features-B8gl38Ue.js → features-D9RrctvA.js} +71 -6
- package/dist/features-D9RrctvA.js.map +1 -0
- package/dist/index.cjs +25 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +25 -8
- package/dist/index.js.map +1 -1
- package/dist/{observability-BEdkwaeY.cjs → observability-B_ARB4Uv.cjs} +85 -24
- package/dist/observability-B_ARB4Uv.cjs.map +1 -0
- package/dist/{observability-B-Kt8vrw.js → observability-CN4Rwgv9.js} +85 -24
- package/dist/observability-CN4Rwgv9.js.map +1 -0
- package/dist/storage/db/index.d.ts +5 -0
- package/dist/storage/db/index.d.ts.map +1 -1
- package/dist/storage/domains/observability/index.d.ts +1 -1
- package/dist/storage/domains/observability/index.d.ts.map +1 -1
- package/dist/storage/domains/observability/preview-compat.d.ts +4 -0
- package/dist/storage/domains/observability/preview-compat.d.ts.map +1 -1
- package/dist/storage/domains/observability/span-query.d.ts +4 -0
- package/dist/storage/domains/observability/span-query.d.ts.map +1 -1
- package/dist/storage/domains/observability/thread-query.d.ts +1 -0
- package/dist/storage/domains/observability/thread-query.d.ts.map +1 -1
- package/dist/storage/domains/observability/trace-aggregate.d.ts.map +1 -1
- package/dist/storage/domains/observability/trace-query.d.ts.map +1 -1
- package/dist/storage/features.d.ts +9 -3
- package/dist/storage/features.d.ts.map +1 -1
- package/dist/storage/index.d.ts +3 -0
- package/dist/storage/index.d.ts.map +1 -1
- package/package.json +2 -2
- package/dist/features-B8gl38Ue.js.map +0 -1
- package/dist/features-DH60yLCA.cjs.map +0 -1
- package/dist/observability-B-Kt8vrw.js.map +0 -1
- package/dist/observability-BEdkwaeY.cjs.map +0 -1
- /package/dist/docs/references/{reference-vectors-duckdb.md → integrations-vectors-duckdb.md} +0 -0
package/README.md
CHANGED
|
@@ -32,7 +32,7 @@ const mastra = new Mastra({
|
|
|
32
32
|
## Documentation
|
|
33
33
|
|
|
34
34
|
- [DuckDB integration guide](https://mastra.ai/integrations/databases/duckdb)
|
|
35
|
-
- [DuckDB vector reference](https://mastra.ai/
|
|
35
|
+
- [DuckDB vector reference](https://mastra.ai/integrations/vectors/duckdb)
|
|
36
36
|
|
|
37
37
|
## Changelog
|
|
38
38
|
|
package/dist/docs/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: mastra-duckdb
|
|
|
3
3
|
description: Documentation for @mastra/duckdb. Use when working with @mastra/duckdb APIs, configuration, or implementation.
|
|
4
4
|
metadata:
|
|
5
5
|
package: "@mastra/duckdb"
|
|
6
|
-
version: "1.
|
|
6
|
+
version: "1.17.0-alpha.1"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
## When to use
|
|
@@ -17,11 +17,11 @@ Read the individual reference documents for detailed explanations and code examp
|
|
|
17
17
|
### Integrations
|
|
18
18
|
|
|
19
19
|
- [DuckDB](references/integrations-databases-duckdb.md) - Store Mastra observability data and metrics in embedded DuckDB for local analytics, either standalone or as a specialized composite storage domain.
|
|
20
|
+
- [DuckDB](references/integrations-vectors-duckdb.md) - Run embedded vector search in DuckDB from Mastra using the VSS extension and HNSW indexes, with no external database server to manage.
|
|
20
21
|
|
|
21
22
|
### Reference
|
|
22
23
|
|
|
23
24
|
- [Reference: Storage retention (prune)](references/reference-storage-retention.md) - prune() deletes rows. It caps growth and is safe to run against large tables (batched, bounded, resumable, cancellable).
|
|
24
|
-
- [Reference: DuckDB vector store](references/reference-vectors-duckdb.md) - The DuckDB storage implementation provides an embedded high-performance vector search solution using DuckDB, an in-process analytical database.
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
Read [assets/SOURCE_MAP.json](assets/SOURCE_MAP.json) for source code references.
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
[DuckDB](https://duckdb.org/) is an embedded, in-process analytical database. The `@mastra/duckdb` package provides an OLAP-backed observability store for local development, suitable for traces, logs, metrics, scores, and feedback without running an external service.
|
|
8
8
|
|
|
9
|
-
For vector search, see the [DuckDB vector store reference](https://mastra.ai/
|
|
9
|
+
For vector search, see the [DuckDB vector store reference](https://mastra.ai/integrations/vectors/duckdb), which is a separate API in the same package.
|
|
10
10
|
|
|
11
11
|
## When to use DuckDB
|
|
12
12
|
|
|
@@ -154,5 +154,5 @@ DuckDB supports the `event-sourced` strategy used by `MastraStorageExporter`, wh
|
|
|
154
154
|
- [Storage overview](https://mastra.ai/reference/storage/overview)
|
|
155
155
|
- [Composite storage](https://mastra.ai/reference/storage/composite)
|
|
156
156
|
- [ClickHouse storage](https://mastra.ai/integrations/databases/clickhouse): Production observability backend
|
|
157
|
-
- [DuckDB vector store](https://mastra.ai/
|
|
157
|
+
- [DuckDB vector store](https://mastra.ai/integrations/vectors/duckdb): Vector search using the same package
|
|
158
158
|
- [Observability overview](https://mastra.ai/docs/observability/overview)
|
|
@@ -66,6 +66,10 @@ var DuckDBConnection = class extends _mastra_core_base.MastraBase {
|
|
|
66
66
|
instance = null;
|
|
67
67
|
initialized = false;
|
|
68
68
|
initPromise = null;
|
|
69
|
+
closed = false;
|
|
70
|
+
activeConnections = 0;
|
|
71
|
+
drainPromise = null;
|
|
72
|
+
finishDrain = null;
|
|
69
73
|
path;
|
|
70
74
|
instanceOptions;
|
|
71
75
|
constructor(config = {}) {
|
|
@@ -80,6 +84,7 @@ var DuckDBConnection = class extends _mastra_core_base.MastraBase {
|
|
|
80
84
|
};
|
|
81
85
|
}
|
|
82
86
|
async initialize() {
|
|
87
|
+
if (this.closed) throw new Error("DuckDB connection is closed");
|
|
83
88
|
if (this.initialized && this.instance) return;
|
|
84
89
|
if (this.initPromise) {
|
|
85
90
|
await this.initPromise;
|
|
@@ -103,8 +108,46 @@ var DuckDBConnection = class extends _mastra_core_base.MastraBase {
|
|
|
103
108
|
/** Create a new connection to the DuckDB instance, initializing if needed. */
|
|
104
109
|
async getConnection() {
|
|
105
110
|
await this.initialize();
|
|
111
|
+
if (this.closed) throw new Error("DuckDB connection is closed");
|
|
106
112
|
if (!this.instance) throw new Error("DuckDB instance not initialized");
|
|
107
|
-
|
|
113
|
+
this.activeConnections++;
|
|
114
|
+
try {
|
|
115
|
+
const connection = await this.instance.connect();
|
|
116
|
+
let released = false;
|
|
117
|
+
const release = () => {
|
|
118
|
+
if (!released) {
|
|
119
|
+
released = true;
|
|
120
|
+
this.releaseConnection();
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
return new Proxy(connection, { get(target, key) {
|
|
124
|
+
const value = Reflect.get(target, key, target);
|
|
125
|
+
if (typeof value !== "function") return value;
|
|
126
|
+
if (key === "closeSync" || key === "disconnectSync" || key === "close" || key === "disconnect") return (...args) => {
|
|
127
|
+
try {
|
|
128
|
+
const result = value.apply(target, args);
|
|
129
|
+
if (result instanceof Promise) return result.finally(release);
|
|
130
|
+
release();
|
|
131
|
+
return result;
|
|
132
|
+
} catch (error) {
|
|
133
|
+
release();
|
|
134
|
+
throw error;
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
return value.bind(target);
|
|
138
|
+
} });
|
|
139
|
+
} catch (error) {
|
|
140
|
+
this.releaseConnection();
|
|
141
|
+
throw error;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
releaseConnection() {
|
|
145
|
+
this.activeConnections--;
|
|
146
|
+
if (this.activeConnections === 0) {
|
|
147
|
+
this.finishDrain?.();
|
|
148
|
+
this.finishDrain = null;
|
|
149
|
+
this.drainPromise = null;
|
|
150
|
+
}
|
|
108
151
|
}
|
|
109
152
|
closeConnection(connection) {
|
|
110
153
|
const conn = connection;
|
|
@@ -265,6 +308,12 @@ var DuckDBConnection = class extends _mastra_core_base.MastraBase {
|
|
|
265
308
|
}
|
|
266
309
|
/** Release the DuckDB instance, allowing garbage collection. */
|
|
267
310
|
async close() {
|
|
311
|
+
this.closed = true;
|
|
312
|
+
await this.initPromise?.catch(() => void 0);
|
|
313
|
+
if (this.activeConnections > 0) {
|
|
314
|
+
this.drainPromise ??= new Promise((resolve) => this.finishDrain = resolve);
|
|
315
|
+
await this.drainPromise;
|
|
316
|
+
}
|
|
268
317
|
if (this.instance) {
|
|
269
318
|
try {
|
|
270
319
|
const instance = this.instance;
|
|
@@ -279,13 +328,29 @@ var DuckDBConnection = class extends _mastra_core_base.MastraBase {
|
|
|
279
328
|
};
|
|
280
329
|
// src/storage/features.ts
|
|
281
330
|
const threadQueryFeatures = typeof _mastra_core_storage.planThreadRowsQuery === "function" ? ["thread-query-rows"] : [];
|
|
282
|
-
const spanQueryFeatures = typeof _mastra_core_storage.planSpanQuery === "function" ? [
|
|
283
|
-
|
|
331
|
+
const spanQueryFeatures = typeof _mastra_core_storage.planSpanQuery === "function" ? [
|
|
332
|
+
"span-query",
|
|
333
|
+
"span-query-context-fields",
|
|
334
|
+
..."model" in (_mastra_core_storage.SPAN_QUERY_FIELD_REGISTRY ?? {}) ? ["span-query-model-fields"] : []
|
|
335
|
+
] : [];
|
|
336
|
+
const spanAggregateFeatures = typeof _mastra_core_storage.planSpanAggregate === "function" ? ["span-aggregate", ..."model" in (_mastra_core_storage.SPAN_AGGREGATE_DIMENSION_REGISTRY ?? {}) ? ["span-aggregate-model-dimensions"] : []] : [];
|
|
284
337
|
/** Core versions without the field reject it in trace query results, so it is only returned when core knows it. */
|
|
285
338
|
const timeToFirstChunkSupported = "timeToFirstChunkMs" in _mastra_core_storage.TRACE_QUERY_FIELD_REGISTRY.trace;
|
|
286
339
|
/** Core before the sort rejects `orderBy` on the field, so the sort is only declared when core plans it. */
|
|
287
340
|
const timeToFirstChunkSortSupported = _mastra_core_storage.TRACE_QUERY_ORDER_FIELDS?.includes("timeToFirstChunkMs") === true;
|
|
288
|
-
|
|
341
|
+
/** Same rule for time to first token: returned and sorted only when core knows the field. */
|
|
342
|
+
const timeToFirstTokenSupported = "timeToFirstTokenMs" in _mastra_core_storage.TRACE_QUERY_FIELD_REGISTRY.trace;
|
|
343
|
+
const timeToFirstTokenSortSupported = _mastra_core_storage.TRACE_QUERY_ORDER_FIELDS?.includes("timeToFirstTokenMs") === true;
|
|
344
|
+
/** Core before the outcome fields rejects their predicates and strict rows, so they are only returned and declared when core knows them. */
|
|
345
|
+
const spanQueryOutcomeFieldsSupported = "outcome" in (_mastra_core_storage.SPAN_QUERY_FIELD_REGISTRY ?? {});
|
|
346
|
+
const traceQueryOutcomeFieldsSupported = "outcome" in (_mastra_core_storage.TRACE_QUERY_FIELD_REGISTRY?.trace ?? {});
|
|
347
|
+
const outcomeFeatures = [...spanQueryOutcomeFieldsSupported ? ["span-query-outcome-fields"] : [], ...traceQueryOutcomeFieldsSupported ? ["trace-query-outcome-fields"] : []];
|
|
348
|
+
const timingFeatures = [
|
|
349
|
+
...timeToFirstChunkSupported ? ["trace-query-time-to-first-chunk"] : [],
|
|
350
|
+
...timeToFirstChunkSortSupported ? ["trace-query-time-to-first-chunk-sort"] : [],
|
|
351
|
+
...timeToFirstTokenSupported ? ["trace-query-time-to-first-token"] : [],
|
|
352
|
+
...timeToFirstTokenSortSupported ? ["trace-query-time-to-first-token-sort"] : []
|
|
353
|
+
];
|
|
289
354
|
Object.defineProperty(exports, "DuckDBConnection", {
|
|
290
355
|
enumerable: true,
|
|
291
356
|
get: function() {
|
|
@@ -310,6 +375,12 @@ Object.defineProperty(exports, "bindParam", {
|
|
|
310
375
|
return bindParam;
|
|
311
376
|
}
|
|
312
377
|
});
|
|
378
|
+
Object.defineProperty(exports, "outcomeFeatures", {
|
|
379
|
+
enumerable: true,
|
|
380
|
+
get: function() {
|
|
381
|
+
return outcomeFeatures;
|
|
382
|
+
}
|
|
383
|
+
});
|
|
313
384
|
Object.defineProperty(exports, "spanAggregateFeatures", {
|
|
314
385
|
enumerable: true,
|
|
315
386
|
get: function() {
|
|
@@ -322,16 +393,16 @@ Object.defineProperty(exports, "spanQueryFeatures", {
|
|
|
322
393
|
return spanQueryFeatures;
|
|
323
394
|
}
|
|
324
395
|
});
|
|
325
|
-
Object.defineProperty(exports, "
|
|
396
|
+
Object.defineProperty(exports, "spanQueryOutcomeFieldsSupported", {
|
|
326
397
|
enumerable: true,
|
|
327
398
|
get: function() {
|
|
328
|
-
return
|
|
399
|
+
return spanQueryOutcomeFieldsSupported;
|
|
329
400
|
}
|
|
330
401
|
});
|
|
331
|
-
Object.defineProperty(exports, "
|
|
402
|
+
Object.defineProperty(exports, "threadQueryFeatures", {
|
|
332
403
|
enumerable: true,
|
|
333
404
|
get: function() {
|
|
334
|
-
return
|
|
405
|
+
return threadQueryFeatures;
|
|
335
406
|
}
|
|
336
407
|
});
|
|
337
408
|
Object.defineProperty(exports, "timeToFirstChunkSupported", {
|
|
@@ -340,5 +411,23 @@ Object.defineProperty(exports, "timeToFirstChunkSupported", {
|
|
|
340
411
|
return timeToFirstChunkSupported;
|
|
341
412
|
}
|
|
342
413
|
});
|
|
414
|
+
Object.defineProperty(exports, "timeToFirstTokenSupported", {
|
|
415
|
+
enumerable: true,
|
|
416
|
+
get: function() {
|
|
417
|
+
return timeToFirstTokenSupported;
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
Object.defineProperty(exports, "timingFeatures", {
|
|
421
|
+
enumerable: true,
|
|
422
|
+
get: function() {
|
|
423
|
+
return timingFeatures;
|
|
424
|
+
}
|
|
425
|
+
});
|
|
426
|
+
Object.defineProperty(exports, "traceQueryOutcomeFieldsSupported", {
|
|
427
|
+
enumerable: true,
|
|
428
|
+
get: function() {
|
|
429
|
+
return traceQueryOutcomeFieldsSupported;
|
|
430
|
+
}
|
|
431
|
+
});
|
|
343
432
|
|
|
344
|
-
//# sourceMappingURL=features-
|
|
433
|
+
//# sourceMappingURL=features-CBdrOdEO.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"features-CBdrOdEO.cjs","names":["DuckDBTimestampValue","DuckDBTimestampTZValue","MastraBase","DuckDBInstance","coreStorage"],"sources":["../src/storage/db/index.ts","../src/storage/features.ts"],"sourcesContent":["import { DuckDBInstance, DuckDBTimestampValue, DuckDBTimestampTZValue } from '@duckdb/node-api';\nimport type { DuckDBPreparedStatement } from '@duckdb/node-api';\nimport { MastraBase } from '@mastra/core/base';\n\n/**\n * Bind a single parameter to a prepared statement using explicit typed methods.\n * This avoids the \"Cannot create values of type ANY\" error that occurs when\n * DuckDB cannot infer parameter types from SQL context (e.g. json_extract_string).\n */\nexport function bindParam(stmt: DuckDBPreparedStatement, index: number, value: unknown): void {\n if (value === null || value === undefined) {\n stmt.bindNull(index);\n } else if (typeof value === 'string') {\n stmt.bindVarchar(index, value);\n } else if (typeof value === 'number') {\n if (Number.isInteger(value) && value >= -2147483648 && value <= 2147483647) {\n stmt.bindInteger(index, value);\n } else {\n stmt.bindDouble(index, value);\n }\n } else if (typeof value === 'boolean') {\n stmt.bindBoolean(index, value);\n } else if (typeof value === 'bigint') {\n stmt.bindBigInt(index, value);\n } else if (value instanceof Date) {\n stmt.bindTimestamp(index, new DuckDBTimestampValue(BigInt(value.getTime()) * 1000n));\n } else if (value instanceof DuckDBTimestampValue) {\n stmt.bindTimestamp(index, value);\n } else if (value instanceof DuckDBTimestampTZValue) {\n stmt.bindTimestampTZ(index, value);\n } else {\n // Fallback: serialize to JSON string\n stmt.bindVarchar(index, JSON.stringify(value));\n }\n}\n\n/** Convert DuckDB-specific return types to plain JS types */\nfunction toJsValue(val: unknown): unknown {\n if (val === null || val === undefined) return val;\n // DuckDBTimestampValue → Date (micros since epoch)\n if (val instanceof DuckDBTimestampValue) {\n return new Date(Number(val.micros / 1000n));\n }\n // BigInt → Number (safe for values we care about)\n if (typeof val === 'bigint') {\n return Number(val);\n }\n return val;\n}\n\n/** A query interrupted at its caller-supplied deadline. */\nexport class DuckDBQueryTimeoutError extends Error {\n constructor() {\n super('DuckDB query exceeded its deadline');\n this.name = 'DuckDBQueryTimeoutError';\n }\n}\n\n/** Configuration for the DuckDB database connection. */\nexport interface DuckDBStorageConfig {\n /** Path to the DuckDB file. Defaults to 'mastra.duckdb'. Use ':memory:' for ephemeral. */\n path?: string;\n /**\n * Maximum memory DuckDB may use (e.g. '2GB', '512MB').\n * @default '2GB'\n * DuckDB's own default is 80% of system RAM, which is far too aggressive for\n * a store embedded in an application server — a single query against a large\n * database can balloon the process by several GB and push the host into\n * swap. Larger-than-memory operations spill to disk for file-backed\n * databases. Raise this for dedicated analytical workloads.\n */\n memoryLimit?: string;\n /**\n * Number of threads DuckDB may use. Defaults to DuckDB's default (one per\n * CPU core). Lower this to keep queries from monopolizing all cores of a\n * shared application server.\n */\n threads?: number;\n}\n\nconst DEFAULT_MEMORY_LIMIT = '2GB';\n\n/**\n * Shared DuckDB connection management for Mastra storage.\n * Defaults to a local file (`mastra.duckdb`) when no path is provided.\n * Pass `path: ':memory:'` for an ephemeral in-memory database.\n */\nexport class DuckDBConnection extends MastraBase {\n private instance: DuckDBInstance | null = null;\n private initialized = false;\n private initPromise: Promise<void> | null = null;\n private closed = false;\n private activeConnections = 0;\n private drainPromise: Promise<void> | null = null;\n private finishDrain: (() => void) | null = null;\n private path: string;\n private instanceOptions: Record<string, string>;\n\n constructor(config: DuckDBStorageConfig = {}) {\n super({ component: 'STORAGE', name: 'DUCKDB' });\n this.path = config.path ?? 'mastra.duckdb';\n this.instanceOptions = {\n max_memory: config.memoryLimit ?? DEFAULT_MEMORY_LIMIT,\n ...(config.threads !== undefined ? { threads: String(config.threads) } : {}),\n };\n }\n\n private async initialize(): Promise<void> {\n if (this.closed) throw new Error('DuckDB connection is closed');\n if (this.initialized && this.instance) return;\n\n if (this.initPromise) {\n await this.initPromise;\n if (this.instance) return;\n this.initPromise = null;\n this.initialized = false;\n }\n\n this.initPromise = (async () => {\n try {\n this.instance = await DuckDBInstance.create(this.path, this.instanceOptions);\n this.initialized = true;\n } catch (error) {\n this.instance = null;\n this.initialized = false;\n this.initPromise = null;\n throw error;\n }\n })();\n\n return this.initPromise;\n }\n\n /** Create a new connection to the DuckDB instance, initializing if needed. */\n async getConnection() {\n await this.initialize();\n if (this.closed) throw new Error('DuckDB connection is closed');\n if (!this.instance) {\n throw new Error('DuckDB instance not initialized');\n }\n this.activeConnections++;\n try {\n const connection = await this.instance.connect();\n let released = false;\n const release = () => {\n if (!released) {\n released = true;\n this.releaseConnection();\n }\n };\n return new Proxy(connection, {\n get(target, key) {\n const value = Reflect.get(target, key, target);\n if (typeof value !== 'function') return value;\n if (key === 'closeSync' || key === 'disconnectSync' || key === 'close' || key === 'disconnect') {\n return (...args: unknown[]) => {\n try {\n const result = value.apply(target, args);\n if (result instanceof Promise) return result.finally(release);\n release();\n return result;\n } catch (error) {\n release();\n throw error;\n }\n };\n }\n return value.bind(target);\n },\n });\n } catch (error) {\n this.releaseConnection();\n throw error;\n }\n }\n\n private releaseConnection(): void {\n this.activeConnections--;\n if (this.activeConnections === 0) {\n this.finishDrain?.();\n this.finishDrain = null;\n this.drainPromise = null;\n }\n }\n\n private closeConnection(connection: unknown): void {\n const conn = connection as {\n closeSync?: () => void;\n disconnectSync?: () => void;\n close?: () => void;\n disconnect?: () => void;\n };\n try {\n if (typeof conn?.closeSync === 'function') {\n conn.closeSync();\n return;\n }\n if (typeof conn?.disconnectSync === 'function') {\n conn.disconnectSync();\n return;\n }\n if (typeof conn?.close === 'function') {\n conn.close();\n return;\n }\n if (typeof conn?.disconnect === 'function') {\n conn.disconnect();\n }\n } catch {\n // Ignore close failures to avoid masking query/execute errors.\n }\n }\n\n /**\n * Execute a SQL query and return results as objects.\n */\n async query<T = Record<string, unknown>>(sql: string, params: unknown[] = [], timeoutMs?: number): Promise<T[]> {\n const connection = await this.getConnection();\n let timedOut = false;\n const timer =\n timeoutMs === undefined\n ? undefined\n : setTimeout(() => {\n timedOut = true;\n connection.interrupt();\n }, timeoutMs);\n try {\n if (params.length === 0) {\n const result = await connection.run(sql);\n const rows = await result.getRows();\n const columns = result.columnNames();\n return rows.map(row => {\n const obj: Record<string, unknown> = {};\n columns.forEach((col, i) => {\n obj[col] = toJsValue(row[i]);\n });\n return obj as T;\n });\n }\n\n let paramIndex = 0;\n const preparedSql = sql.replace(/\\?/g, () => `$${++paramIndex}`);\n const stmt = await connection.prepare(preparedSql);\n for (let i = 0; i < params.length; i++) {\n bindParam(stmt, i + 1, params[i]);\n }\n const result = await stmt.run();\n const rows = await result.getRows();\n const columns = result.columnNames();\n return rows.map(row => {\n const obj: Record<string, unknown> = {};\n columns.forEach((col, i) => {\n obj[col] = toJsValue(row[i]);\n });\n return obj as T;\n });\n } catch (error) {\n if (timedOut) throw new DuckDBQueryTimeoutError();\n throw error;\n } finally {\n if (timer !== undefined) clearTimeout(timer);\n this.closeConnection(connection);\n }\n }\n\n /**\n * Execute a SQL statement without returning results.\n */\n async execute(sql: string, params: unknown[] = []): Promise<void> {\n const connection = await this.getConnection();\n try {\n if (params.length === 0) {\n await connection.run(sql);\n return;\n }\n let paramIndex = 0;\n const preparedSql = sql.replace(/\\?/g, () => `$${++paramIndex}`);\n const stmt = await connection.prepare(preparedSql);\n for (let i = 0; i < params.length; i++) {\n bindParam(stmt, i + 1, params[i]);\n }\n await stmt.run();\n } finally {\n this.closeConnection(connection);\n }\n }\n\n /** Delete one bounded retention batch and return the number of rows removed. */\n async pruneBatch({\n tableName,\n column,\n cutoff,\n limit,\n }: {\n tableName: string;\n column: string;\n cutoff: Date;\n limit: number;\n }): Promise<number> {\n const identifier = /^[A-Za-z_][A-Za-z0-9_]*$/;\n if (!identifier.test(tableName) || !identifier.test(column)) {\n throw new Error(`Invalid retention identifier: ${tableName}.${column}`);\n }\n\n const rows = await this.query(\n `DELETE FROM ${tableName}\n WHERE rowid IN (\n SELECT rowid FROM ${tableName}\n WHERE ${column} < ?\n ORDER BY ${column}\n LIMIT ?\n )\n RETURNING 1 AS deleted`,\n [cutoff, limit],\n );\n return rows.length;\n }\n\n /** Execute parameterized statements atomically using a single DuckDB connection. */\n async executeTransaction(statements: readonly { sql: string; params?: readonly unknown[] }[]): Promise<void> {\n if (statements.length === 0) return;\n\n const connection = await this.getConnection();\n try {\n await connection.run('BEGIN TRANSACTION');\n for (const statement of statements) {\n const params = statement.params ?? [];\n if (params.length === 0) {\n await connection.run(statement.sql);\n continue;\n }\n let paramIndex = 0;\n const preparedSql = statement.sql.replace(/\\?/g, () => `$${++paramIndex}`);\n const prepared = await connection.prepare(preparedSql);\n for (let i = 0; i < params.length; i++) {\n bindParam(prepared, i + 1, params[i]);\n }\n await prepared.run();\n }\n await connection.run('COMMIT');\n } catch (error) {\n await connection.run('ROLLBACK').catch(() => undefined);\n throw error;\n } finally {\n this.closeConnection(connection);\n }\n }\n\n /**\n * Execute multiple SQL statements in order using a single DuckDB connection.\n *\n * This is intended for schema setup/migrations where statements have no\n * parameters and must remain ordered, but opening a connection per statement\n * would dominate initialization cost. Blank statements are skipped. Like\n * calling execute() repeatedly, this does not wrap statements in a transaction,\n * so prior statements can remain applied if a later statement fails.\n */\n async executeBatch(sqlStatements: readonly string[]): Promise<void> {\n const statements = sqlStatements.map(statement => statement.trim()).filter(Boolean);\n if (statements.length === 0) return;\n\n const connection = await this.getConnection();\n try {\n const sql =\n statements.map((statement, i) => `-- executeBatch statement ${i + 1}\\n${statement}`).join('\\n;\\n') + '\\n;';\n await connection.run(sql);\n } finally {\n this.closeConnection(connection);\n }\n }\n\n /**\n * Escape a value for safe inline SQL use.\n * DuckDB prepared statements can't handle NULL for parameters typed as ANY,\n * so for complex INSERT/UPDATE operations we inline values safely.\n */\n static sqlValue(value: unknown): string {\n if (value === null || value === undefined) return 'NULL';\n if (typeof value === 'number') {\n if (!Number.isFinite(value)) return 'NULL';\n return String(value);\n }\n if (typeof value === 'boolean') return value ? 'TRUE' : 'FALSE';\n if (value instanceof Date) return `'${value.toISOString()}'::TIMESTAMP`;\n if (typeof value === 'string') return `'${value.replace(/'/g, \"''\")}'`;\n // Objects/arrays → JSON string\n return `'${JSON.stringify(value).replace(/'/g, \"''\")}'`;\n }\n\n /** Release the DuckDB instance, allowing garbage collection. */\n async close(): Promise<void> {\n this.closed = true;\n await this.initPromise?.catch(() => undefined);\n if (this.activeConnections > 0) {\n this.drainPromise ??= new Promise<void>(resolve => (this.finishDrain = resolve));\n await this.drainPromise;\n }\n if (this.instance) {\n try {\n const instance = this.instance as unknown as { closeSync?: () => void; close?: () => void };\n if (typeof instance.closeSync === 'function') {\n instance.closeSync();\n } else if (typeof instance.close === 'function') {\n instance.close();\n }\n } catch {\n // Ignore close failures to allow cleanup of references.\n }\n this.instance = null;\n this.initialized = false;\n this.initPromise = null;\n }\n }\n}\n","import * as coreStorage from '@mastra/core/storage';\n\nexport const threadQueryFeatures =\n typeof coreStorage.planThreadRowsQuery === 'function' ? (['thread-query-rows'] as const) : ([] as const);\n\nexport const spanQueryFeatures =\n typeof coreStorage.planSpanQuery === 'function'\n ? ([\n 'span-query',\n 'span-query-context-fields',\n // Core before the fields rejects `model`/`provider` predicates, so only declare them when core plans them.\n ...('model' in (coreStorage.SPAN_QUERY_FIELD_REGISTRY ?? {}) ? (['span-query-model-fields'] as const) : []),\n ] as const)\n : ([] as const);\n\nexport const spanAggregateFeatures =\n typeof coreStorage.planSpanAggregate === 'function'\n ? ([\n 'span-aggregate',\n // Core before the dimensions rejects `model`/`provider` in `groupBy`, so only declare them when core plans them.\n ...('model' in (coreStorage.SPAN_AGGREGATE_DIMENSION_REGISTRY ?? {})\n ? (['span-aggregate-model-dimensions'] as const)\n : []),\n ] as const)\n : ([] as const);\n\n/** Core versions without the field reject it in trace query results, so it is only returned when core knows it. */\nexport const timeToFirstChunkSupported = 'timeToFirstChunkMs' in coreStorage.TRACE_QUERY_FIELD_REGISTRY.trace;\n\n/** Core before the sort rejects `orderBy` on the field, so the sort is only declared when core plans it. */\nconst timeToFirstChunkSortSupported = coreStorage.TRACE_QUERY_ORDER_FIELDS?.includes('timeToFirstChunkMs') === true;\n\n/** Same rule for time to first token: returned and sorted only when core knows the field. */\nexport const timeToFirstTokenSupported = 'timeToFirstTokenMs' in coreStorage.TRACE_QUERY_FIELD_REGISTRY.trace;\nconst timeToFirstTokenSortSupported = coreStorage.TRACE_QUERY_ORDER_FIELDS?.includes('timeToFirstTokenMs') === true;\n\n/** Core before the outcome fields rejects their predicates and strict rows, so they are only returned and declared when core knows them. */\nexport const spanQueryOutcomeFieldsSupported = 'outcome' in (coreStorage.SPAN_QUERY_FIELD_REGISTRY ?? {});\nexport const traceQueryOutcomeFieldsSupported = 'outcome' in (coreStorage.TRACE_QUERY_FIELD_REGISTRY?.trace ?? {});\n\nexport const outcomeFeatures: readonly ('span-query-outcome-fields' | 'trace-query-outcome-fields')[] = [\n ...(spanQueryOutcomeFieldsSupported ? (['span-query-outcome-fields'] as const) : []),\n ...(traceQueryOutcomeFieldsSupported ? (['trace-query-outcome-fields'] as const) : []),\n];\n\nexport const timingFeatures = [\n ...(timeToFirstChunkSupported ? (['trace-query-time-to-first-chunk'] as const) : []),\n ...(timeToFirstChunkSortSupported ? (['trace-query-time-to-first-chunk-sort'] as const) : []),\n ...(timeToFirstTokenSupported ? (['trace-query-time-to-first-token'] as const) : []),\n ...(timeToFirstTokenSortSupported ? (['trace-query-time-to-first-token-sort'] as const) : []),\n] as const;\n"],"mappings":"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"}
|
|
@@ -44,6 +44,10 @@ var DuckDBConnection = class extends MastraBase {
|
|
|
44
44
|
instance = null;
|
|
45
45
|
initialized = false;
|
|
46
46
|
initPromise = null;
|
|
47
|
+
closed = false;
|
|
48
|
+
activeConnections = 0;
|
|
49
|
+
drainPromise = null;
|
|
50
|
+
finishDrain = null;
|
|
47
51
|
path;
|
|
48
52
|
instanceOptions;
|
|
49
53
|
constructor(config = {}) {
|
|
@@ -58,6 +62,7 @@ var DuckDBConnection = class extends MastraBase {
|
|
|
58
62
|
};
|
|
59
63
|
}
|
|
60
64
|
async initialize() {
|
|
65
|
+
if (this.closed) throw new Error("DuckDB connection is closed");
|
|
61
66
|
if (this.initialized && this.instance) return;
|
|
62
67
|
if (this.initPromise) {
|
|
63
68
|
await this.initPromise;
|
|
@@ -81,8 +86,46 @@ var DuckDBConnection = class extends MastraBase {
|
|
|
81
86
|
/** Create a new connection to the DuckDB instance, initializing if needed. */
|
|
82
87
|
async getConnection() {
|
|
83
88
|
await this.initialize();
|
|
89
|
+
if (this.closed) throw new Error("DuckDB connection is closed");
|
|
84
90
|
if (!this.instance) throw new Error("DuckDB instance not initialized");
|
|
85
|
-
|
|
91
|
+
this.activeConnections++;
|
|
92
|
+
try {
|
|
93
|
+
const connection = await this.instance.connect();
|
|
94
|
+
let released = false;
|
|
95
|
+
const release = () => {
|
|
96
|
+
if (!released) {
|
|
97
|
+
released = true;
|
|
98
|
+
this.releaseConnection();
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
return new Proxy(connection, { get(target, key) {
|
|
102
|
+
const value = Reflect.get(target, key, target);
|
|
103
|
+
if (typeof value !== "function") return value;
|
|
104
|
+
if (key === "closeSync" || key === "disconnectSync" || key === "close" || key === "disconnect") return (...args) => {
|
|
105
|
+
try {
|
|
106
|
+
const result = value.apply(target, args);
|
|
107
|
+
if (result instanceof Promise) return result.finally(release);
|
|
108
|
+
release();
|
|
109
|
+
return result;
|
|
110
|
+
} catch (error) {
|
|
111
|
+
release();
|
|
112
|
+
throw error;
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
return value.bind(target);
|
|
116
|
+
} });
|
|
117
|
+
} catch (error) {
|
|
118
|
+
this.releaseConnection();
|
|
119
|
+
throw error;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
releaseConnection() {
|
|
123
|
+
this.activeConnections--;
|
|
124
|
+
if (this.activeConnections === 0) {
|
|
125
|
+
this.finishDrain?.();
|
|
126
|
+
this.finishDrain = null;
|
|
127
|
+
this.drainPromise = null;
|
|
128
|
+
}
|
|
86
129
|
}
|
|
87
130
|
closeConnection(connection) {
|
|
88
131
|
const conn = connection;
|
|
@@ -243,6 +286,12 @@ var DuckDBConnection = class extends MastraBase {
|
|
|
243
286
|
}
|
|
244
287
|
/** Release the DuckDB instance, allowing garbage collection. */
|
|
245
288
|
async close() {
|
|
289
|
+
this.closed = true;
|
|
290
|
+
await this.initPromise?.catch(() => void 0);
|
|
291
|
+
if (this.activeConnections > 0) {
|
|
292
|
+
this.drainPromise ??= new Promise((resolve) => this.finishDrain = resolve);
|
|
293
|
+
await this.drainPromise;
|
|
294
|
+
}
|
|
246
295
|
if (this.instance) {
|
|
247
296
|
try {
|
|
248
297
|
const instance = this.instance;
|
|
@@ -257,13 +306,29 @@ var DuckDBConnection = class extends MastraBase {
|
|
|
257
306
|
};
|
|
258
307
|
// src/storage/features.ts
|
|
259
308
|
const threadQueryFeatures = typeof coreStorage.planThreadRowsQuery === "function" ? ["thread-query-rows"] : [];
|
|
260
|
-
const spanQueryFeatures = typeof coreStorage.planSpanQuery === "function" ? [
|
|
261
|
-
|
|
309
|
+
const spanQueryFeatures = typeof coreStorage.planSpanQuery === "function" ? [
|
|
310
|
+
"span-query",
|
|
311
|
+
"span-query-context-fields",
|
|
312
|
+
..."model" in (coreStorage.SPAN_QUERY_FIELD_REGISTRY ?? {}) ? ["span-query-model-fields"] : []
|
|
313
|
+
] : [];
|
|
314
|
+
const spanAggregateFeatures = typeof coreStorage.planSpanAggregate === "function" ? ["span-aggregate", ..."model" in (coreStorage.SPAN_AGGREGATE_DIMENSION_REGISTRY ?? {}) ? ["span-aggregate-model-dimensions"] : []] : [];
|
|
262
315
|
/** Core versions without the field reject it in trace query results, so it is only returned when core knows it. */
|
|
263
316
|
const timeToFirstChunkSupported = "timeToFirstChunkMs" in coreStorage.TRACE_QUERY_FIELD_REGISTRY.trace;
|
|
264
317
|
/** Core before the sort rejects `orderBy` on the field, so the sort is only declared when core plans it. */
|
|
265
318
|
const timeToFirstChunkSortSupported = coreStorage.TRACE_QUERY_ORDER_FIELDS?.includes("timeToFirstChunkMs") === true;
|
|
266
|
-
|
|
267
|
-
|
|
319
|
+
/** Same rule for time to first token: returned and sorted only when core knows the field. */
|
|
320
|
+
const timeToFirstTokenSupported = "timeToFirstTokenMs" in coreStorage.TRACE_QUERY_FIELD_REGISTRY.trace;
|
|
321
|
+
const timeToFirstTokenSortSupported = coreStorage.TRACE_QUERY_ORDER_FIELDS?.includes("timeToFirstTokenMs") === true;
|
|
322
|
+
/** Core before the outcome fields rejects their predicates and strict rows, so they are only returned and declared when core knows them. */
|
|
323
|
+
const spanQueryOutcomeFieldsSupported = "outcome" in (coreStorage.SPAN_QUERY_FIELD_REGISTRY ?? {});
|
|
324
|
+
const traceQueryOutcomeFieldsSupported = "outcome" in (coreStorage.TRACE_QUERY_FIELD_REGISTRY?.trace ?? {});
|
|
325
|
+
const outcomeFeatures = [...spanQueryOutcomeFieldsSupported ? ["span-query-outcome-fields"] : [], ...traceQueryOutcomeFieldsSupported ? ["trace-query-outcome-fields"] : []];
|
|
326
|
+
const timingFeatures = [
|
|
327
|
+
...timeToFirstChunkSupported ? ["trace-query-time-to-first-chunk"] : [],
|
|
328
|
+
...timeToFirstChunkSortSupported ? ["trace-query-time-to-first-chunk-sort"] : [],
|
|
329
|
+
...timeToFirstTokenSupported ? ["trace-query-time-to-first-token"] : [],
|
|
330
|
+
...timeToFirstTokenSortSupported ? ["trace-query-time-to-first-token-sort"] : []
|
|
331
|
+
];
|
|
332
|
+
export { threadQueryFeatures as a, timingFeatures as c, DuckDBQueryTimeoutError as d, bindParam as f, spanQueryOutcomeFieldsSupported as i, traceQueryOutcomeFieldsSupported as l, spanAggregateFeatures as n, timeToFirstChunkSupported as o, spanQueryFeatures as r, timeToFirstTokenSupported as s, outcomeFeatures as t, DuckDBConnection as u };
|
|
268
333
|
|
|
269
|
-
//# sourceMappingURL=features-
|
|
334
|
+
//# sourceMappingURL=features-D9RrctvA.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"features-D9RrctvA.js","names":[],"sources":["../src/storage/db/index.ts","../src/storage/features.ts"],"sourcesContent":["import { DuckDBInstance, DuckDBTimestampValue, DuckDBTimestampTZValue } from '@duckdb/node-api';\nimport type { DuckDBPreparedStatement } from '@duckdb/node-api';\nimport { MastraBase } from '@mastra/core/base';\n\n/**\n * Bind a single parameter to a prepared statement using explicit typed methods.\n * This avoids the \"Cannot create values of type ANY\" error that occurs when\n * DuckDB cannot infer parameter types from SQL context (e.g. json_extract_string).\n */\nexport function bindParam(stmt: DuckDBPreparedStatement, index: number, value: unknown): void {\n if (value === null || value === undefined) {\n stmt.bindNull(index);\n } else if (typeof value === 'string') {\n stmt.bindVarchar(index, value);\n } else if (typeof value === 'number') {\n if (Number.isInteger(value) && value >= -2147483648 && value <= 2147483647) {\n stmt.bindInteger(index, value);\n } else {\n stmt.bindDouble(index, value);\n }\n } else if (typeof value === 'boolean') {\n stmt.bindBoolean(index, value);\n } else if (typeof value === 'bigint') {\n stmt.bindBigInt(index, value);\n } else if (value instanceof Date) {\n stmt.bindTimestamp(index, new DuckDBTimestampValue(BigInt(value.getTime()) * 1000n));\n } else if (value instanceof DuckDBTimestampValue) {\n stmt.bindTimestamp(index, value);\n } else if (value instanceof DuckDBTimestampTZValue) {\n stmt.bindTimestampTZ(index, value);\n } else {\n // Fallback: serialize to JSON string\n stmt.bindVarchar(index, JSON.stringify(value));\n }\n}\n\n/** Convert DuckDB-specific return types to plain JS types */\nfunction toJsValue(val: unknown): unknown {\n if (val === null || val === undefined) return val;\n // DuckDBTimestampValue → Date (micros since epoch)\n if (val instanceof DuckDBTimestampValue) {\n return new Date(Number(val.micros / 1000n));\n }\n // BigInt → Number (safe for values we care about)\n if (typeof val === 'bigint') {\n return Number(val);\n }\n return val;\n}\n\n/** A query interrupted at its caller-supplied deadline. */\nexport class DuckDBQueryTimeoutError extends Error {\n constructor() {\n super('DuckDB query exceeded its deadline');\n this.name = 'DuckDBQueryTimeoutError';\n }\n}\n\n/** Configuration for the DuckDB database connection. */\nexport interface DuckDBStorageConfig {\n /** Path to the DuckDB file. Defaults to 'mastra.duckdb'. Use ':memory:' for ephemeral. */\n path?: string;\n /**\n * Maximum memory DuckDB may use (e.g. '2GB', '512MB').\n * @default '2GB'\n * DuckDB's own default is 80% of system RAM, which is far too aggressive for\n * a store embedded in an application server — a single query against a large\n * database can balloon the process by several GB and push the host into\n * swap. Larger-than-memory operations spill to disk for file-backed\n * databases. Raise this for dedicated analytical workloads.\n */\n memoryLimit?: string;\n /**\n * Number of threads DuckDB may use. Defaults to DuckDB's default (one per\n * CPU core). Lower this to keep queries from monopolizing all cores of a\n * shared application server.\n */\n threads?: number;\n}\n\nconst DEFAULT_MEMORY_LIMIT = '2GB';\n\n/**\n * Shared DuckDB connection management for Mastra storage.\n * Defaults to a local file (`mastra.duckdb`) when no path is provided.\n * Pass `path: ':memory:'` for an ephemeral in-memory database.\n */\nexport class DuckDBConnection extends MastraBase {\n private instance: DuckDBInstance | null = null;\n private initialized = false;\n private initPromise: Promise<void> | null = null;\n private closed = false;\n private activeConnections = 0;\n private drainPromise: Promise<void> | null = null;\n private finishDrain: (() => void) | null = null;\n private path: string;\n private instanceOptions: Record<string, string>;\n\n constructor(config: DuckDBStorageConfig = {}) {\n super({ component: 'STORAGE', name: 'DUCKDB' });\n this.path = config.path ?? 'mastra.duckdb';\n this.instanceOptions = {\n max_memory: config.memoryLimit ?? DEFAULT_MEMORY_LIMIT,\n ...(config.threads !== undefined ? { threads: String(config.threads) } : {}),\n };\n }\n\n private async initialize(): Promise<void> {\n if (this.closed) throw new Error('DuckDB connection is closed');\n if (this.initialized && this.instance) return;\n\n if (this.initPromise) {\n await this.initPromise;\n if (this.instance) return;\n this.initPromise = null;\n this.initialized = false;\n }\n\n this.initPromise = (async () => {\n try {\n this.instance = await DuckDBInstance.create(this.path, this.instanceOptions);\n this.initialized = true;\n } catch (error) {\n this.instance = null;\n this.initialized = false;\n this.initPromise = null;\n throw error;\n }\n })();\n\n return this.initPromise;\n }\n\n /** Create a new connection to the DuckDB instance, initializing if needed. */\n async getConnection() {\n await this.initialize();\n if (this.closed) throw new Error('DuckDB connection is closed');\n if (!this.instance) {\n throw new Error('DuckDB instance not initialized');\n }\n this.activeConnections++;\n try {\n const connection = await this.instance.connect();\n let released = false;\n const release = () => {\n if (!released) {\n released = true;\n this.releaseConnection();\n }\n };\n return new Proxy(connection, {\n get(target, key) {\n const value = Reflect.get(target, key, target);\n if (typeof value !== 'function') return value;\n if (key === 'closeSync' || key === 'disconnectSync' || key === 'close' || key === 'disconnect') {\n return (...args: unknown[]) => {\n try {\n const result = value.apply(target, args);\n if (result instanceof Promise) return result.finally(release);\n release();\n return result;\n } catch (error) {\n release();\n throw error;\n }\n };\n }\n return value.bind(target);\n },\n });\n } catch (error) {\n this.releaseConnection();\n throw error;\n }\n }\n\n private releaseConnection(): void {\n this.activeConnections--;\n if (this.activeConnections === 0) {\n this.finishDrain?.();\n this.finishDrain = null;\n this.drainPromise = null;\n }\n }\n\n private closeConnection(connection: unknown): void {\n const conn = connection as {\n closeSync?: () => void;\n disconnectSync?: () => void;\n close?: () => void;\n disconnect?: () => void;\n };\n try {\n if (typeof conn?.closeSync === 'function') {\n conn.closeSync();\n return;\n }\n if (typeof conn?.disconnectSync === 'function') {\n conn.disconnectSync();\n return;\n }\n if (typeof conn?.close === 'function') {\n conn.close();\n return;\n }\n if (typeof conn?.disconnect === 'function') {\n conn.disconnect();\n }\n } catch {\n // Ignore close failures to avoid masking query/execute errors.\n }\n }\n\n /**\n * Execute a SQL query and return results as objects.\n */\n async query<T = Record<string, unknown>>(sql: string, params: unknown[] = [], timeoutMs?: number): Promise<T[]> {\n const connection = await this.getConnection();\n let timedOut = false;\n const timer =\n timeoutMs === undefined\n ? undefined\n : setTimeout(() => {\n timedOut = true;\n connection.interrupt();\n }, timeoutMs);\n try {\n if (params.length === 0) {\n const result = await connection.run(sql);\n const rows = await result.getRows();\n const columns = result.columnNames();\n return rows.map(row => {\n const obj: Record<string, unknown> = {};\n columns.forEach((col, i) => {\n obj[col] = toJsValue(row[i]);\n });\n return obj as T;\n });\n }\n\n let paramIndex = 0;\n const preparedSql = sql.replace(/\\?/g, () => `$${++paramIndex}`);\n const stmt = await connection.prepare(preparedSql);\n for (let i = 0; i < params.length; i++) {\n bindParam(stmt, i + 1, params[i]);\n }\n const result = await stmt.run();\n const rows = await result.getRows();\n const columns = result.columnNames();\n return rows.map(row => {\n const obj: Record<string, unknown> = {};\n columns.forEach((col, i) => {\n obj[col] = toJsValue(row[i]);\n });\n return obj as T;\n });\n } catch (error) {\n if (timedOut) throw new DuckDBQueryTimeoutError();\n throw error;\n } finally {\n if (timer !== undefined) clearTimeout(timer);\n this.closeConnection(connection);\n }\n }\n\n /**\n * Execute a SQL statement without returning results.\n */\n async execute(sql: string, params: unknown[] = []): Promise<void> {\n const connection = await this.getConnection();\n try {\n if (params.length === 0) {\n await connection.run(sql);\n return;\n }\n let paramIndex = 0;\n const preparedSql = sql.replace(/\\?/g, () => `$${++paramIndex}`);\n const stmt = await connection.prepare(preparedSql);\n for (let i = 0; i < params.length; i++) {\n bindParam(stmt, i + 1, params[i]);\n }\n await stmt.run();\n } finally {\n this.closeConnection(connection);\n }\n }\n\n /** Delete one bounded retention batch and return the number of rows removed. */\n async pruneBatch({\n tableName,\n column,\n cutoff,\n limit,\n }: {\n tableName: string;\n column: string;\n cutoff: Date;\n limit: number;\n }): Promise<number> {\n const identifier = /^[A-Za-z_][A-Za-z0-9_]*$/;\n if (!identifier.test(tableName) || !identifier.test(column)) {\n throw new Error(`Invalid retention identifier: ${tableName}.${column}`);\n }\n\n const rows = await this.query(\n `DELETE FROM ${tableName}\n WHERE rowid IN (\n SELECT rowid FROM ${tableName}\n WHERE ${column} < ?\n ORDER BY ${column}\n LIMIT ?\n )\n RETURNING 1 AS deleted`,\n [cutoff, limit],\n );\n return rows.length;\n }\n\n /** Execute parameterized statements atomically using a single DuckDB connection. */\n async executeTransaction(statements: readonly { sql: string; params?: readonly unknown[] }[]): Promise<void> {\n if (statements.length === 0) return;\n\n const connection = await this.getConnection();\n try {\n await connection.run('BEGIN TRANSACTION');\n for (const statement of statements) {\n const params = statement.params ?? [];\n if (params.length === 0) {\n await connection.run(statement.sql);\n continue;\n }\n let paramIndex = 0;\n const preparedSql = statement.sql.replace(/\\?/g, () => `$${++paramIndex}`);\n const prepared = await connection.prepare(preparedSql);\n for (let i = 0; i < params.length; i++) {\n bindParam(prepared, i + 1, params[i]);\n }\n await prepared.run();\n }\n await connection.run('COMMIT');\n } catch (error) {\n await connection.run('ROLLBACK').catch(() => undefined);\n throw error;\n } finally {\n this.closeConnection(connection);\n }\n }\n\n /**\n * Execute multiple SQL statements in order using a single DuckDB connection.\n *\n * This is intended for schema setup/migrations where statements have no\n * parameters and must remain ordered, but opening a connection per statement\n * would dominate initialization cost. Blank statements are skipped. Like\n * calling execute() repeatedly, this does not wrap statements in a transaction,\n * so prior statements can remain applied if a later statement fails.\n */\n async executeBatch(sqlStatements: readonly string[]): Promise<void> {\n const statements = sqlStatements.map(statement => statement.trim()).filter(Boolean);\n if (statements.length === 0) return;\n\n const connection = await this.getConnection();\n try {\n const sql =\n statements.map((statement, i) => `-- executeBatch statement ${i + 1}\\n${statement}`).join('\\n;\\n') + '\\n;';\n await connection.run(sql);\n } finally {\n this.closeConnection(connection);\n }\n }\n\n /**\n * Escape a value for safe inline SQL use.\n * DuckDB prepared statements can't handle NULL for parameters typed as ANY,\n * so for complex INSERT/UPDATE operations we inline values safely.\n */\n static sqlValue(value: unknown): string {\n if (value === null || value === undefined) return 'NULL';\n if (typeof value === 'number') {\n if (!Number.isFinite(value)) return 'NULL';\n return String(value);\n }\n if (typeof value === 'boolean') return value ? 'TRUE' : 'FALSE';\n if (value instanceof Date) return `'${value.toISOString()}'::TIMESTAMP`;\n if (typeof value === 'string') return `'${value.replace(/'/g, \"''\")}'`;\n // Objects/arrays → JSON string\n return `'${JSON.stringify(value).replace(/'/g, \"''\")}'`;\n }\n\n /** Release the DuckDB instance, allowing garbage collection. */\n async close(): Promise<void> {\n this.closed = true;\n await this.initPromise?.catch(() => undefined);\n if (this.activeConnections > 0) {\n this.drainPromise ??= new Promise<void>(resolve => (this.finishDrain = resolve));\n await this.drainPromise;\n }\n if (this.instance) {\n try {\n const instance = this.instance as unknown as { closeSync?: () => void; close?: () => void };\n if (typeof instance.closeSync === 'function') {\n instance.closeSync();\n } else if (typeof instance.close === 'function') {\n instance.close();\n }\n } catch {\n // Ignore close failures to allow cleanup of references.\n }\n this.instance = null;\n this.initialized = false;\n this.initPromise = null;\n }\n }\n}\n","import * as coreStorage from '@mastra/core/storage';\n\nexport const threadQueryFeatures =\n typeof coreStorage.planThreadRowsQuery === 'function' ? (['thread-query-rows'] as const) : ([] as const);\n\nexport const spanQueryFeatures =\n typeof coreStorage.planSpanQuery === 'function'\n ? ([\n 'span-query',\n 'span-query-context-fields',\n // Core before the fields rejects `model`/`provider` predicates, so only declare them when core plans them.\n ...('model' in (coreStorage.SPAN_QUERY_FIELD_REGISTRY ?? {}) ? (['span-query-model-fields'] as const) : []),\n ] as const)\n : ([] as const);\n\nexport const spanAggregateFeatures =\n typeof coreStorage.planSpanAggregate === 'function'\n ? ([\n 'span-aggregate',\n // Core before the dimensions rejects `model`/`provider` in `groupBy`, so only declare them when core plans them.\n ...('model' in (coreStorage.SPAN_AGGREGATE_DIMENSION_REGISTRY ?? {})\n ? (['span-aggregate-model-dimensions'] as const)\n : []),\n ] as const)\n : ([] as const);\n\n/** Core versions without the field reject it in trace query results, so it is only returned when core knows it. */\nexport const timeToFirstChunkSupported = 'timeToFirstChunkMs' in coreStorage.TRACE_QUERY_FIELD_REGISTRY.trace;\n\n/** Core before the sort rejects `orderBy` on the field, so the sort is only declared when core plans it. */\nconst timeToFirstChunkSortSupported = coreStorage.TRACE_QUERY_ORDER_FIELDS?.includes('timeToFirstChunkMs') === true;\n\n/** Same rule for time to first token: returned and sorted only when core knows the field. */\nexport const timeToFirstTokenSupported = 'timeToFirstTokenMs' in coreStorage.TRACE_QUERY_FIELD_REGISTRY.trace;\nconst timeToFirstTokenSortSupported = coreStorage.TRACE_QUERY_ORDER_FIELDS?.includes('timeToFirstTokenMs') === true;\n\n/** Core before the outcome fields rejects their predicates and strict rows, so they are only returned and declared when core knows them. */\nexport const spanQueryOutcomeFieldsSupported = 'outcome' in (coreStorage.SPAN_QUERY_FIELD_REGISTRY ?? {});\nexport const traceQueryOutcomeFieldsSupported = 'outcome' in (coreStorage.TRACE_QUERY_FIELD_REGISTRY?.trace ?? {});\n\nexport const outcomeFeatures: readonly ('span-query-outcome-fields' | 'trace-query-outcome-fields')[] = [\n ...(spanQueryOutcomeFieldsSupported ? (['span-query-outcome-fields'] as const) : []),\n ...(traceQueryOutcomeFieldsSupported ? (['trace-query-outcome-fields'] as const) : []),\n];\n\nexport const timingFeatures = [\n ...(timeToFirstChunkSupported ? (['trace-query-time-to-first-chunk'] as const) : []),\n ...(timeToFirstChunkSortSupported ? (['trace-query-time-to-first-chunk-sort'] as const) : []),\n ...(timeToFirstTokenSupported ? (['trace-query-time-to-first-token'] as const) : []),\n ...(timeToFirstTokenSortSupported ? (['trace-query-time-to-first-token-sort'] as const) : []),\n] as const;\n"],"mappings":";;;;;;;;;AASA,SAAgB,UAAU,MAA+B,OAAe,OAAsB;CAC5F,IAAI,UAAU,QAAQ,UAAU,KAAA,GAC9B,KAAK,SAAS,KAAK;MACd,IAAI,OAAO,UAAU,UAC1B,KAAK,YAAY,OAAO,KAAK;MACxB,IAAI,OAAO,UAAU,UAAU;EACpC,IAAI,OAAO,UAAU,KAAK,KAAK,SAAS,eAAe,SAAS,YAC9D,KAAK,YAAY,OAAO,KAAK;OAE7B,KAAK,WAAW,OAAO,KAAK;CAEhC,OAAO,IAAI,OAAO,UAAU,WAC1B,KAAK,YAAY,OAAO,KAAK;MACxB,IAAI,OAAO,UAAU,UAC1B,KAAK,WAAW,OAAO,KAAK;MACvB,IAAI,iBAAiB,MAC1B,KAAK,cAAc,OAAO,IAAI,qBAAqB,OAAO,MAAM,QAAQ,CAAC,IAAI,KAAK,CAAC;MAC9E,IAAI,iBAAiB,sBAC1B,KAAK,cAAc,OAAO,KAAK;MAC1B,IAAI,iBAAiB,wBAC1B,KAAK,gBAAgB,OAAO,KAAK;MAGjC,KAAK,YAAY,OAAO,KAAK,UAAU,KAAK,CAAC;AAEjD;;AAGA,SAAS,UAAU,KAAuB;CACxC,IAAI,QAAQ,QAAQ,QAAQ,KAAA,GAAW,OAAO;CAE9C,IAAI,eAAe,sBACjB,OAAO,IAAI,KAAK,OAAO,IAAI,SAAS,KAAK,CAAC;CAG5C,IAAI,OAAO,QAAQ,UACjB,OAAO,OAAO,GAAG;CAEnB,OAAO;AACT;;AAGA,IAAa,0BAAb,cAA6C,MAAM;CACjD,cAAc;EACZ,MAAM,oCAAoC;EAC1C,KAAK,OAAO;CACd;AACF;AAwBA,MAAM,uBAAuB;;;;;;AAO7B,IAAa,mBAAb,cAAsC,WAAW;CAC/C,WAA0C;CAC1C,cAAsB;CACtB,cAA4C;CAC5C,SAAiB;CACjB,oBAA4B;CAC5B,eAA6C;CAC7C,cAA2C;CAC3C;CACA;CAEA,YAAY,SAA8B,CAAC,GAAG;EAC5C,MAAM;GAAE,WAAW;GAAW,MAAM;EAAS,CAAC;EAC9C,KAAK,OAAO,OAAO,QAAQ;EAC3B,KAAK,kBAAkB;GACrB,YAAY,OAAO,eAAe;GAClC,GAAI,OAAO,YAAY,KAAA,IAAY,EAAE,SAAS,OAAO,OAAO,OAAO,EAAE,IAAI,CAAC;EAC5E;CACF;CAEA,MAAc,aAA4B;EACxC,IAAI,KAAK,QAAQ,MAAM,IAAI,MAAM,6BAA6B;EAC9D,IAAI,KAAK,eAAe,KAAK,UAAU;EAEvC,IAAI,KAAK,aAAa;GACpB,MAAM,KAAK;GACX,IAAI,KAAK,UAAU;GACnB,KAAK,cAAc;GACnB,KAAK,cAAc;EACrB;EAEA,KAAK,eAAe,YAAY;GAC9B,IAAI;IACF,KAAK,WAAW,MAAM,eAAe,OAAO,KAAK,MAAM,KAAK,eAAe;IAC3E,KAAK,cAAc;GACrB,SAAS,OAAO;IACd,KAAK,WAAW;IAChB,KAAK,cAAc;IACnB,KAAK,cAAc;IACnB,MAAM;GACR;EACF,EAAA,CAAG;EAEH,OAAO,KAAK;CACd;;CAGA,MAAM,gBAAgB;EACpB,MAAM,KAAK,WAAW;EACtB,IAAI,KAAK,QAAQ,MAAM,IAAI,MAAM,6BAA6B;EAC9D,IAAI,CAAC,KAAK,UACR,MAAM,IAAI,MAAM,iCAAiC;EAEnD,KAAK;EACL,IAAI;GACF,MAAM,aAAa,MAAM,KAAK,SAAS,QAAQ;GAC/C,IAAI,WAAW;GACf,MAAM,gBAAgB;IACpB,IAAI,CAAC,UAAU;KACb,WAAW;KACX,KAAK,kBAAkB;IACzB;GACF;GACA,OAAO,IAAI,MAAM,YAAY,EAC3B,IAAI,QAAQ,KAAK;IACf,MAAM,QAAQ,QAAQ,IAAI,QAAQ,KAAK,MAAM;IAC7C,IAAI,OAAO,UAAU,YAAY,OAAO;IACxC,IAAI,QAAQ,eAAe,QAAQ,oBAAoB,QAAQ,WAAW,QAAQ,cAChF,QAAQ,GAAG,SAAoB;KAC7B,IAAI;MACF,MAAM,SAAS,MAAM,MAAM,QAAQ,IAAI;MACvC,IAAI,kBAAkB,SAAS,OAAO,OAAO,QAAQ,OAAO;MAC5D,QAAQ;MACR,OAAO;KACT,SAAS,OAAO;MACd,QAAQ;MACR,MAAM;KACR;IACF;IAEF,OAAO,MAAM,KAAK,MAAM;GAC1B,EACF,CAAC;EACH,SAAS,OAAO;GACd,KAAK,kBAAkB;GACvB,MAAM;EACR;CACF;CAEA,oBAAkC;EAChC,KAAK;EACL,IAAI,KAAK,sBAAsB,GAAG;GAChC,KAAK,cAAc;GACnB,KAAK,cAAc;GACnB,KAAK,eAAe;EACtB;CACF;CAEA,gBAAwB,YAA2B;EACjD,MAAM,OAAO;EAMb,IAAI;GACF,IAAI,OAAO,MAAM,cAAc,YAAY;IACzC,KAAK,UAAU;IACf;GACF;GACA,IAAI,OAAO,MAAM,mBAAmB,YAAY;IAC9C,KAAK,eAAe;IACpB;GACF;GACA,IAAI,OAAO,MAAM,UAAU,YAAY;IACrC,KAAK,MAAM;IACX;GACF;GACA,IAAI,OAAO,MAAM,eAAe,YAC9B,KAAK,WAAW;EAEpB,QAAQ,CAER;CACF;;;;CAKA,MAAM,MAAmC,KAAa,SAAoB,CAAC,GAAG,WAAkC;EAC9G,MAAM,aAAa,MAAM,KAAK,cAAc;EAC5C,IAAI,WAAW;EACf,MAAM,QACJ,cAAc,KAAA,IACV,KAAA,IACA,iBAAiB;GACf,WAAW;GACX,WAAW,UAAU;EACvB,GAAG,SAAS;EAClB,IAAI;GACF,IAAI,OAAO,WAAW,GAAG;IACvB,MAAM,SAAS,MAAM,WAAW,IAAI,GAAG;IACvC,MAAM,OAAO,MAAM,OAAO,QAAQ;IAClC,MAAM,UAAU,OAAO,YAAY;IACnC,OAAO,KAAK,KAAI,QAAO;KACrB,MAAM,MAA+B,CAAC;KACtC,QAAQ,SAAS,KAAK,MAAM;MAC1B,IAAI,OAAO,UAAU,IAAI,EAAE;KAC7B,CAAC;KACD,OAAO;IACT,CAAC;GACH;GAEA,IAAI,aAAa;GACjB,MAAM,cAAc,IAAI,QAAQ,aAAa,IAAI,EAAE,YAAY;GAC/D,MAAM,OAAO,MAAM,WAAW,QAAQ,WAAW;GACjD,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KACjC,UAAU,MAAM,IAAI,GAAG,OAAO,EAAE;GAElC,MAAM,SAAS,MAAM,KAAK,IAAI;GAC9B,MAAM,OAAO,MAAM,OAAO,QAAQ;GAClC,MAAM,UAAU,OAAO,YAAY;GACnC,OAAO,KAAK,KAAI,QAAO;IACrB,MAAM,MAA+B,CAAC;IACtC,QAAQ,SAAS,KAAK,MAAM;KAC1B,IAAI,OAAO,UAAU,IAAI,EAAE;IAC7B,CAAC;IACD,OAAO;GACT,CAAC;EACH,SAAS,OAAO;GACd,IAAI,UAAU,MAAM,IAAI,wBAAwB;GAChD,MAAM;EACR,UAAU;GACR,IAAI,UAAU,KAAA,GAAW,aAAa,KAAK;GAC3C,KAAK,gBAAgB,UAAU;EACjC;CACF;;;;CAKA,MAAM,QAAQ,KAAa,SAAoB,CAAC,GAAkB;EAChE,MAAM,aAAa,MAAM,KAAK,cAAc;EAC5C,IAAI;GACF,IAAI,OAAO,WAAW,GAAG;IACvB,MAAM,WAAW,IAAI,GAAG;IACxB;GACF;GACA,IAAI,aAAa;GACjB,MAAM,cAAc,IAAI,QAAQ,aAAa,IAAI,EAAE,YAAY;GAC/D,MAAM,OAAO,MAAM,WAAW,QAAQ,WAAW;GACjD,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KACjC,UAAU,MAAM,IAAI,GAAG,OAAO,EAAE;GAElC,MAAM,KAAK,IAAI;EACjB,UAAU;GACR,KAAK,gBAAgB,UAAU;EACjC;CACF;;CAGA,MAAM,WAAW,EACf,WACA,QACA,QACA,SAMkB;EAClB,MAAM,aAAa;EACnB,IAAI,CAAC,WAAW,KAAK,SAAS,KAAK,CAAC,WAAW,KAAK,MAAM,GACxD,MAAM,IAAI,MAAM,iCAAiC,UAAU,GAAG,QAAQ;EAcxE,QAAO,MAXY,KAAK,MACtB,eAAe,UAAU;;6BAEF,UAAU;iBACtB,OAAO;oBACJ,OAAO;;;gCAIrB,CAAC,QAAQ,KAAK,CAChB,EAAA,CACY;CACd;;CAGA,MAAM,mBAAmB,YAAoF;EAC3G,IAAI,WAAW,WAAW,GAAG;EAE7B,MAAM,aAAa,MAAM,KAAK,cAAc;EAC5C,IAAI;GACF,MAAM,WAAW,IAAI,mBAAmB;GACxC,KAAK,MAAM,aAAa,YAAY;IAClC,MAAM,SAAS,UAAU,UAAU,CAAC;IACpC,IAAI,OAAO,WAAW,GAAG;KACvB,MAAM,WAAW,IAAI,UAAU,GAAG;KAClC;IACF;IACA,IAAI,aAAa;IACjB,MAAM,cAAc,UAAU,IAAI,QAAQ,aAAa,IAAI,EAAE,YAAY;IACzE,MAAM,WAAW,MAAM,WAAW,QAAQ,WAAW;IACrD,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KACjC,UAAU,UAAU,IAAI,GAAG,OAAO,EAAE;IAEtC,MAAM,SAAS,IAAI;GACrB;GACA,MAAM,WAAW,IAAI,QAAQ;EAC/B,SAAS,OAAO;GACd,MAAM,WAAW,IAAI,UAAU,CAAC,CAAC,YAAY,KAAA,CAAS;GACtD,MAAM;EACR,UAAU;GACR,KAAK,gBAAgB,UAAU;EACjC;CACF;;;;;;;;;;CAWA,MAAM,aAAa,eAAiD;EAClE,MAAM,aAAa,cAAc,KAAI,cAAa,UAAU,KAAK,CAAC,CAAC,CAAC,OAAO,OAAO;EAClF,IAAI,WAAW,WAAW,GAAG;EAE7B,MAAM,aAAa,MAAM,KAAK,cAAc;EAC5C,IAAI;GACF,MAAM,MACJ,WAAW,KAAK,WAAW,MAAM,6BAA6B,IAAI,EAAE,IAAI,WAAW,CAAC,CAAC,KAAK,OAAO,IAAI;GACvG,MAAM,WAAW,IAAI,GAAG;EAC1B,UAAU;GACR,KAAK,gBAAgB,UAAU;EACjC;CACF;;;;;;CAOA,OAAO,SAAS,OAAwB;EACtC,IAAI,UAAU,QAAQ,UAAU,KAAA,GAAW,OAAO;EAClD,IAAI,OAAO,UAAU,UAAU;GAC7B,IAAI,CAAC,OAAO,SAAS,KAAK,GAAG,OAAO;GACpC,OAAO,OAAO,KAAK;EACrB;EACA,IAAI,OAAO,UAAU,WAAW,OAAO,QAAQ,SAAS;EACxD,IAAI,iBAAiB,MAAM,OAAO,IAAI,MAAM,YAAY,EAAE;EAC1D,IAAI,OAAO,UAAU,UAAU,OAAO,IAAI,MAAM,QAAQ,MAAM,IAAI,EAAE;EAEpE,OAAO,IAAI,KAAK,UAAU,KAAK,CAAC,CAAC,QAAQ,MAAM,IAAI,EAAE;CACvD;;CAGA,MAAM,QAAuB;EAC3B,KAAK,SAAS;EACd,MAAM,KAAK,aAAa,YAAY,KAAA,CAAS;EAC7C,IAAI,KAAK,oBAAoB,GAAG;GAC9B,KAAK,iBAAiB,IAAI,SAAc,YAAY,KAAK,cAAc,OAAQ;GAC/E,MAAM,KAAK;EACb;EACA,IAAI,KAAK,UAAU;GACjB,IAAI;IACF,MAAM,WAAW,KAAK;IACtB,IAAI,OAAO,SAAS,cAAc,YAChC,SAAS,UAAU;SACd,IAAI,OAAO,SAAS,UAAU,YACnC,SAAS,MAAM;GAEnB,QAAQ,CAER;GACA,KAAK,WAAW;GAChB,KAAK,cAAc;GACnB,KAAK,cAAc;EACrB;CACF;AACF;;AC3ZA,MAAa,sBACX,OAAO,YAAY,wBAAwB,aAAc,CAAC,mBAAmB,IAAe,CAAC;AAE/F,MAAa,oBACX,OAAO,YAAY,kBAAkB,aAChC;CACC;CACA;CAEA,GAAI,YAAY,YAAY,6BAA6B,CAAC,KAAM,CAAC,yBAAyB,IAAc,CAAC;AAC3G,IACC,CAAC;AAER,MAAa,wBACX,OAAO,YAAY,sBAAsB,aACpC,CACC,kBAEA,GAAI,YAAY,YAAY,qCAAqC,CAAC,KAC7D,CAAC,iCAAiC,IACnC,CAAC,CACP,IACC,CAAC;;AAGR,MAAa,4BAA4B,wBAAwB,YAAY,2BAA2B;;AAGxG,MAAM,gCAAgC,YAAY,0BAA0B,SAAS,oBAAoB,MAAM;;AAG/G,MAAa,4BAA4B,wBAAwB,YAAY,2BAA2B;AACxG,MAAM,gCAAgC,YAAY,0BAA0B,SAAS,oBAAoB,MAAM;;AAG/G,MAAa,kCAAkC,cAAc,YAAY,6BAA6B,CAAC;AACvG,MAAa,mCAAmC,cAAc,YAAY,4BAA4B,SAAS,CAAC;AAEhH,MAAa,kBAA2F,CACtG,GAAI,kCAAmC,CAAC,2BAA2B,IAAc,CAAC,GAClF,GAAI,mCAAoC,CAAC,4BAA4B,IAAc,CAAC,CACtF;AAEA,MAAa,iBAAiB;CAC5B,GAAI,4BAA6B,CAAC,iCAAiC,IAAc,CAAC;CAClF,GAAI,gCAAiC,CAAC,sCAAsC,IAAc,CAAC;CAC3F,GAAI,4BAA6B,CAAC,iCAAiC,IAAc,CAAC;CAClF,GAAI,gCAAiC,CAAC,sCAAsC,IAAc,CAAC;AAC7F"}
|
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_features = require("./features-
|
|
2
|
+
const require_features = require("./features-CBdrOdEO.cjs");
|
|
3
3
|
let _duckdb_node_api = require("@duckdb/node-api");
|
|
4
4
|
let _mastra_core_error = require("@mastra/core/error");
|
|
5
5
|
let _mastra_core_storage = require("@mastra/core/storage");
|
|
@@ -505,7 +505,8 @@ const DUCKDB_OBSERVABILITY_FEATURES = [
|
|
|
505
505
|
"trace-query-tenant-scope",
|
|
506
506
|
"feedback",
|
|
507
507
|
"trace-query-context-ids",
|
|
508
|
-
...require_features.
|
|
508
|
+
...require_features.timingFeatures,
|
|
509
|
+
...require_features.outcomeFeatures,
|
|
509
510
|
"trace-query-root-span-fields",
|
|
510
511
|
"trace-query-root-entity-id"
|
|
511
512
|
];
|
|
@@ -530,7 +531,8 @@ const DUCKDB_OBSERVABILITY_DELTA_FEATURES = [
|
|
|
530
531
|
"trace-query-tenant-scope",
|
|
531
532
|
"feedback",
|
|
532
533
|
"trace-query-context-ids",
|
|
533
|
-
...require_features.
|
|
534
|
+
...require_features.timingFeatures,
|
|
535
|
+
...require_features.outcomeFeatures,
|
|
534
536
|
"trace-query-root-span-fields",
|
|
535
537
|
"trace-query-root-entity-id"
|
|
536
538
|
];
|
|
@@ -549,6 +551,8 @@ var ObservabilityStorageDuckDB = class extends _mastra_core_storage.Observabilit
|
|
|
549
551
|
delegate = null;
|
|
550
552
|
loadPromise = null;
|
|
551
553
|
unavailableError = null;
|
|
554
|
+
pendingInits = /* @__PURE__ */ new Set();
|
|
555
|
+
closed = false;
|
|
552
556
|
constructor(config) {
|
|
553
557
|
super();
|
|
554
558
|
this.db = config.db;
|
|
@@ -564,7 +568,7 @@ var ObservabilityStorageDuckDB = class extends _mastra_core_storage.Observabilit
|
|
|
564
568
|
async loadDelegate() {
|
|
565
569
|
if (this.delegate) return this.delegate;
|
|
566
570
|
if (this.unavailableError) return null;
|
|
567
|
-
if (!this.loadPromise) this.loadPromise = Promise.resolve().then(() => require("./observability-
|
|
571
|
+
if (!this.loadPromise) this.loadPromise = Promise.resolve().then(() => require("./observability-B_ARB4Uv.cjs")).then(({ ObservabilityStorageDuckDB }) => {
|
|
568
572
|
const delegate = new ObservabilityStorageDuckDB({ db: this.db });
|
|
569
573
|
this.delegate = delegate;
|
|
570
574
|
return delegate;
|
|
@@ -596,9 +600,22 @@ var ObservabilityStorageDuckDB = class extends _mastra_core_storage.Observabilit
|
|
|
596
600
|
return DUCKDB_OBSERVABILITY_DELTA_FEATURES;
|
|
597
601
|
}
|
|
598
602
|
async init(...args) {
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
603
|
+
if (this.closed) throw new Error("DuckDB observability storage is closed");
|
|
604
|
+
const init = (async () => {
|
|
605
|
+
const delegate = await this.loadDelegate();
|
|
606
|
+
if (delegate && !this.closed) await delegate.init(...args);
|
|
607
|
+
})();
|
|
608
|
+
this.pendingInits.add(init);
|
|
609
|
+
try {
|
|
610
|
+
await init;
|
|
611
|
+
} finally {
|
|
612
|
+
this.pendingInits.delete(init);
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
async close() {
|
|
616
|
+
this.closed = true;
|
|
617
|
+
await Promise.allSettled(this.pendingInits);
|
|
618
|
+
await this.db.close();
|
|
602
619
|
}
|
|
603
620
|
async migrateSpans(...args) {
|
|
604
621
|
return (await this.requireDelegate()).migrateSpans(...args);
|
|
@@ -825,7 +842,7 @@ var DuckDBStore = class extends _mastra_core_storage.MastraCompositeStore {
|
|
|
825
842
|
* Safe to call more than once; subsequent calls are no-ops.
|
|
826
843
|
*/
|
|
827
844
|
async close() {
|
|
828
|
-
await this.
|
|
845
|
+
await this.observabilityStore.close();
|
|
829
846
|
}
|
|
830
847
|
};
|
|
831
848
|
exports.DuckDBConnection = require_features.DuckDBConnection;
|