@mastra/duckdb 1.17.0-alpha.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.
Files changed (31) hide show
  1. package/README.md +1 -1
  2. package/dist/docs/SKILL.md +2 -2
  3. package/dist/docs/assets/SOURCE_MAP.json +1 -1
  4. package/dist/docs/references/integrations-databases-duckdb.md +2 -2
  5. package/dist/{features-CMkGwt1J.cjs → features-CBdrOdEO.cjs} +29 -3
  6. package/dist/{features-CMkGwt1J.cjs.map → features-CBdrOdEO.cjs.map} +1 -1
  7. package/dist/{features-dc98I6Rx.js → features-D9RrctvA.js} +12 -4
  8. package/dist/{features-dc98I6Rx.js.map → features-D9RrctvA.js.map} +1 -1
  9. package/dist/index.cjs +4 -2
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.js +4 -2
  12. package/dist/index.js.map +1 -1
  13. package/dist/{observability-Dr89aflR.cjs → observability-B_ARB4Uv.cjs} +61 -20
  14. package/dist/observability-B_ARB4Uv.cjs.map +1 -0
  15. package/dist/{observability-DlRTQlrI.js → observability-CN4Rwgv9.js} +61 -20
  16. package/dist/observability-CN4Rwgv9.js.map +1 -0
  17. package/dist/storage/domains/observability/index.d.ts +1 -1
  18. package/dist/storage/domains/observability/index.d.ts.map +1 -1
  19. package/dist/storage/domains/observability/preview-compat.d.ts +3 -0
  20. package/dist/storage/domains/observability/preview-compat.d.ts.map +1 -1
  21. package/dist/storage/domains/observability/span-query.d.ts +3 -0
  22. package/dist/storage/domains/observability/span-query.d.ts.map +1 -1
  23. package/dist/storage/domains/observability/trace-aggregate.d.ts.map +1 -1
  24. package/dist/storage/domains/observability/trace-query.d.ts.map +1 -1
  25. package/dist/storage/features.d.ts +6 -2
  26. package/dist/storage/features.d.ts.map +1 -1
  27. package/dist/storage/index.d.ts.map +1 -1
  28. package/package.json +2 -2
  29. package/dist/observability-DlRTQlrI.js.map +0 -1
  30. package/dist/observability-Dr89aflR.cjs.map +0 -1
  31. /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/reference/vectors/duckdb)
35
+ - [DuckDB vector reference](https://mastra.ai/integrations/vectors/duckdb)
36
36
 
37
37
  ## Changelog
38
38
 
@@ -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.17.0-alpha.0"
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.
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.17.0-alpha.0",
2
+ "version": "1.17.0-alpha.1",
3
3
  "package": "@mastra/duckdb",
4
4
  "exports": {},
5
5
  "modules": {}
@@ -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/reference/vectors/duckdb), which is a separate API in the same package.
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/reference/vectors/duckdb): Vector search using the same package
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)
@@ -328,8 +328,12 @@ var DuckDBConnection = class extends _mastra_core_base.MastraBase {
328
328
  };
329
329
  // src/storage/features.ts
330
330
  const threadQueryFeatures = typeof _mastra_core_storage.planThreadRowsQuery === "function" ? ["thread-query-rows"] : [];
331
- const spanQueryFeatures = typeof _mastra_core_storage.planSpanQuery === "function" ? ["span-query", "span-query-context-fields"] : [];
332
- const spanAggregateFeatures = typeof _mastra_core_storage.planSpanAggregate === "function" ? ["span-aggregate"] : [];
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"] : []] : [];
333
337
  /** Core versions without the field reject it in trace query results, so it is only returned when core knows it. */
334
338
  const timeToFirstChunkSupported = "timeToFirstChunkMs" in _mastra_core_storage.TRACE_QUERY_FIELD_REGISTRY.trace;
335
339
  /** Core before the sort rejects `orderBy` on the field, so the sort is only declared when core plans it. */
@@ -337,6 +341,10 @@ const timeToFirstChunkSortSupported = _mastra_core_storage.TRACE_QUERY_ORDER_FIE
337
341
  /** Same rule for time to first token: returned and sorted only when core knows the field. */
338
342
  const timeToFirstTokenSupported = "timeToFirstTokenMs" in _mastra_core_storage.TRACE_QUERY_FIELD_REGISTRY.trace;
339
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"] : []];
340
348
  const timingFeatures = [
341
349
  ...timeToFirstChunkSupported ? ["trace-query-time-to-first-chunk"] : [],
342
350
  ...timeToFirstChunkSortSupported ? ["trace-query-time-to-first-chunk-sort"] : [],
@@ -367,6 +375,12 @@ Object.defineProperty(exports, "bindParam", {
367
375
  return bindParam;
368
376
  }
369
377
  });
378
+ Object.defineProperty(exports, "outcomeFeatures", {
379
+ enumerable: true,
380
+ get: function() {
381
+ return outcomeFeatures;
382
+ }
383
+ });
370
384
  Object.defineProperty(exports, "spanAggregateFeatures", {
371
385
  enumerable: true,
372
386
  get: function() {
@@ -379,6 +393,12 @@ Object.defineProperty(exports, "spanQueryFeatures", {
379
393
  return spanQueryFeatures;
380
394
  }
381
395
  });
396
+ Object.defineProperty(exports, "spanQueryOutcomeFieldsSupported", {
397
+ enumerable: true,
398
+ get: function() {
399
+ return spanQueryOutcomeFieldsSupported;
400
+ }
401
+ });
382
402
  Object.defineProperty(exports, "threadQueryFeatures", {
383
403
  enumerable: true,
384
404
  get: function() {
@@ -403,5 +423,11 @@ Object.defineProperty(exports, "timingFeatures", {
403
423
  return timingFeatures;
404
424
  }
405
425
  });
426
+ Object.defineProperty(exports, "traceQueryOutcomeFieldsSupported", {
427
+ enumerable: true,
428
+ get: function() {
429
+ return traceQueryOutcomeFieldsSupported;
430
+ }
431
+ });
406
432
 
407
- //# sourceMappingURL=features-CMkGwt1J.cjs.map
433
+ //# sourceMappingURL=features-CBdrOdEO.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"features-CMkGwt1J.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 ? (['span-query', 'span-query-context-fields'] as const)\n : ([] as const);\n\nexport const spanAggregateFeatures =\n typeof coreStorage.planSpanAggregate === 'function' ? (['span-aggregate'] as const) : ([] 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\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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"}
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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"}
@@ -306,8 +306,12 @@ var DuckDBConnection = class extends MastraBase {
306
306
  };
307
307
  // src/storage/features.ts
308
308
  const threadQueryFeatures = typeof coreStorage.planThreadRowsQuery === "function" ? ["thread-query-rows"] : [];
309
- const spanQueryFeatures = typeof coreStorage.planSpanQuery === "function" ? ["span-query", "span-query-context-fields"] : [];
310
- const spanAggregateFeatures = typeof coreStorage.planSpanAggregate === "function" ? ["span-aggregate"] : [];
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"] : []] : [];
311
315
  /** Core versions without the field reject it in trace query results, so it is only returned when core knows it. */
312
316
  const timeToFirstChunkSupported = "timeToFirstChunkMs" in coreStorage.TRACE_QUERY_FIELD_REGISTRY.trace;
313
317
  /** Core before the sort rejects `orderBy` on the field, so the sort is only declared when core plans it. */
@@ -315,12 +319,16 @@ const timeToFirstChunkSortSupported = coreStorage.TRACE_QUERY_ORDER_FIELDS?.incl
315
319
  /** Same rule for time to first token: returned and sorted only when core knows the field. */
316
320
  const timeToFirstTokenSupported = "timeToFirstTokenMs" in coreStorage.TRACE_QUERY_FIELD_REGISTRY.trace;
317
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"] : []];
318
326
  const timingFeatures = [
319
327
  ...timeToFirstChunkSupported ? ["trace-query-time-to-first-chunk"] : [],
320
328
  ...timeToFirstChunkSortSupported ? ["trace-query-time-to-first-chunk-sort"] : [],
321
329
  ...timeToFirstTokenSupported ? ["trace-query-time-to-first-token"] : [],
322
330
  ...timeToFirstTokenSortSupported ? ["trace-query-time-to-first-token-sort"] : []
323
331
  ];
324
- export { timeToFirstTokenSupported as a, DuckDBQueryTimeoutError as c, timeToFirstChunkSupported as i, bindParam as l, spanQueryFeatures as n, timingFeatures as o, threadQueryFeatures as r, DuckDBConnection as s, spanAggregateFeatures as t };
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 };
325
333
 
326
- //# sourceMappingURL=features-dc98I6Rx.js.map
334
+ //# sourceMappingURL=features-D9RrctvA.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"features-dc98I6Rx.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 ? (['span-query', 'span-query-context-fields'] as const)\n : ([] as const);\n\nexport const spanAggregateFeatures =\n typeof coreStorage.planSpanAggregate === 'function' ? (['span-aggregate'] as const) : ([] 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\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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"}
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":"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"}
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_features = require("./features-CMkGwt1J.cjs");
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");
@@ -506,6 +506,7 @@ const DUCKDB_OBSERVABILITY_FEATURES = [
506
506
  "feedback",
507
507
  "trace-query-context-ids",
508
508
  ...require_features.timingFeatures,
509
+ ...require_features.outcomeFeatures,
509
510
  "trace-query-root-span-fields",
510
511
  "trace-query-root-entity-id"
511
512
  ];
@@ -531,6 +532,7 @@ const DUCKDB_OBSERVABILITY_DELTA_FEATURES = [
531
532
  "feedback",
532
533
  "trace-query-context-ids",
533
534
  ...require_features.timingFeatures,
535
+ ...require_features.outcomeFeatures,
534
536
  "trace-query-root-span-fields",
535
537
  "trace-query-root-entity-id"
536
538
  ];
@@ -566,7 +568,7 @@ var ObservabilityStorageDuckDB = class extends _mastra_core_storage.Observabilit
566
568
  async loadDelegate() {
567
569
  if (this.delegate) return this.delegate;
568
570
  if (this.unavailableError) return null;
569
- if (!this.loadPromise) this.loadPromise = Promise.resolve().then(() => require("./observability-Dr89aflR.cjs")).then(({ ObservabilityStorageDuckDB }) => {
571
+ if (!this.loadPromise) this.loadPromise = Promise.resolve().then(() => require("./observability-B_ARB4Uv.cjs")).then(({ ObservabilityStorageDuckDB }) => {
570
572
  const delegate = new ObservabilityStorageDuckDB({ db: this.db });
571
573
  this.delegate = delegate;
572
574
  return delegate;