sensemaking 0.21.0 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/chunk/group.d.cts +0 -2
  3. package/dist/cjs/chunk/group.d.ts +0 -2
  4. package/dist/cjs/chunk/group.js +25 -62
  5. package/dist/cjs/chunk/group.js.map +1 -1
  6. package/dist/cjs/chunk/index.d.cts +1 -1
  7. package/dist/cjs/chunk/index.d.ts +1 -1
  8. package/dist/cjs/chunk/index.js +3 -2
  9. package/dist/cjs/chunk/index.js.map +1 -1
  10. package/dist/cjs/chunk/parse.js +46 -29
  11. package/dist/cjs/chunk/parse.js.map +1 -1
  12. package/dist/cjs/chunk/tokens.d.cts +2 -0
  13. package/dist/cjs/chunk/tokens.d.ts +2 -0
  14. package/dist/cjs/chunk/tokens.js +50 -0
  15. package/dist/cjs/chunk/tokens.js.map +1 -0
  16. package/dist/cjs/commands/search.js +1 -1
  17. package/dist/cjs/commands/search.js.map +1 -1
  18. package/dist/cjs/config/validate.js.map +1 -1
  19. package/dist/cjs/index.d.cts +1 -1
  20. package/dist/cjs/index.d.ts +1 -1
  21. package/dist/cjs/index.js.map +1 -1
  22. package/dist/cjs/scan/pool.d.cts +1 -0
  23. package/dist/cjs/scan/pool.d.ts +1 -0
  24. package/dist/cjs/scan/pool.js +2 -1
  25. package/dist/cjs/scan/pool.js.map +1 -1
  26. package/dist/cjs/scan/reparse.d.cts +1 -0
  27. package/dist/cjs/scan/reparse.d.ts +1 -0
  28. package/dist/cjs/scan/reparse.js +6 -3
  29. package/dist/cjs/scan/reparse.js.map +1 -1
  30. package/dist/cjs/store/builder.d.cts +2 -0
  31. package/dist/cjs/store/builder.d.ts +2 -0
  32. package/dist/cjs/store/builder.js.map +1 -1
  33. package/dist/cjs/store/duckdb/connection.d.cts +4 -1
  34. package/dist/cjs/store/duckdb/connection.d.ts +4 -1
  35. package/dist/cjs/store/duckdb/connection.js +1 -0
  36. package/dist/cjs/store/duckdb/connection.js.map +1 -1
  37. package/dist/cjs/store/duckdb/reconcile.js +105 -1
  38. package/dist/cjs/store/duckdb/reconcile.js.map +1 -1
  39. package/dist/cjs/store/index.d.cts +1 -5
  40. package/dist/cjs/store/index.d.ts +1 -5
  41. package/dist/cjs/store/index.js +9 -46
  42. package/dist/cjs/store/index.js.map +1 -1
  43. package/dist/cjs/store/lock-wait.d.cts +2 -0
  44. package/dist/cjs/store/lock-wait.d.ts +2 -0
  45. package/dist/cjs/store/lock-wait.js +51 -0
  46. package/dist/cjs/store/lock-wait.js.map +1 -0
  47. package/dist/cjs/store/open.d.cts +2 -4
  48. package/dist/cjs/store/open.d.ts +2 -4
  49. package/dist/cjs/store/open.js +29 -66
  50. package/dist/cjs/store/open.js.map +1 -1
  51. package/dist/cjs/store/reconcile.d.cts +3 -0
  52. package/dist/cjs/store/reconcile.d.ts +3 -0
  53. package/dist/cjs/store/reconcile.js +418 -226
  54. package/dist/cjs/store/reconcile.js.map +1 -1
  55. package/dist/cjs/store/sqlite/lexical.js +1 -1
  56. package/dist/cjs/store/sqlite/lexical.js.map +1 -1
  57. package/dist/cjs/store/sqlite/store.js +0 -1
  58. package/dist/cjs/store/sqlite/store.js.map +1 -1
  59. package/dist/cjs/store/stages.d.cts +18 -0
  60. package/dist/cjs/store/stages.d.ts +18 -0
  61. package/dist/cjs/store/stages.js +372 -0
  62. package/dist/cjs/store/stages.js.map +1 -0
  63. package/dist/cjs/store/turso/store.js.map +1 -1
  64. package/dist/cjs/store/types.d.cts +2 -1
  65. package/dist/cjs/store/types.d.ts +2 -1
  66. package/dist/cjs/store/types.js +0 -1
  67. package/dist/cjs/store/types.js.map +1 -1
  68. package/dist/cjs/text/segment.js +7 -5
  69. package/dist/cjs/text/segment.js.map +1 -1
  70. package/dist/cjs/watch.js +162 -107
  71. package/dist/cjs/watch.js.map +1 -1
  72. package/dist/cjs/workers/parse.d.cts +1 -0
  73. package/dist/cjs/workers/parse.d.ts +1 -0
  74. package/dist/cjs/workers/parse.js +4 -1
  75. package/dist/cjs/workers/parse.js.map +1 -1
  76. package/dist/esm/chunk/group.d.ts +0 -2
  77. package/dist/esm/chunk/group.js +14 -24
  78. package/dist/esm/chunk/group.js.map +1 -1
  79. package/dist/esm/chunk/index.d.ts +1 -1
  80. package/dist/esm/chunk/index.js +1 -1
  81. package/dist/esm/chunk/index.js.map +1 -1
  82. package/dist/esm/chunk/parse.js +41 -29
  83. package/dist/esm/chunk/parse.js.map +1 -1
  84. package/dist/esm/chunk/tokens.d.ts +2 -0
  85. package/dist/esm/chunk/tokens.js +15 -0
  86. package/dist/esm/chunk/tokens.js.map +1 -0
  87. package/dist/esm/commands/search.js +1 -1
  88. package/dist/esm/commands/search.js.map +1 -1
  89. package/dist/esm/config/validate.js +2 -2
  90. package/dist/esm/config/validate.js.map +1 -1
  91. package/dist/esm/index.d.ts +1 -1
  92. package/dist/esm/index.js.map +1 -1
  93. package/dist/esm/scan/pool.d.ts +1 -0
  94. package/dist/esm/scan/pool.js +2 -1
  95. package/dist/esm/scan/pool.js.map +1 -1
  96. package/dist/esm/scan/reparse.d.ts +1 -0
  97. package/dist/esm/scan/reparse.js +5 -2
  98. package/dist/esm/scan/reparse.js.map +1 -1
  99. package/dist/esm/store/builder.d.ts +2 -0
  100. package/dist/esm/store/builder.js.map +1 -1
  101. package/dist/esm/store/duckdb/connection.d.ts +4 -1
  102. package/dist/esm/store/duckdb/connection.js +1 -0
  103. package/dist/esm/store/duckdb/connection.js.map +1 -1
  104. package/dist/esm/store/duckdb/reconcile.js +34 -1
  105. package/dist/esm/store/duckdb/reconcile.js.map +1 -1
  106. package/dist/esm/store/index.d.ts +1 -5
  107. package/dist/esm/store/index.js +6 -28
  108. package/dist/esm/store/index.js.map +1 -1
  109. package/dist/esm/store/lock-wait.d.ts +2 -0
  110. package/dist/esm/store/lock-wait.js +36 -0
  111. package/dist/esm/store/lock-wait.js.map +1 -0
  112. package/dist/esm/store/open.d.ts +2 -4
  113. package/dist/esm/store/open.js +17 -32
  114. package/dist/esm/store/open.js.map +1 -1
  115. package/dist/esm/store/reconcile.d.ts +3 -0
  116. package/dist/esm/store/reconcile.js +77 -40
  117. package/dist/esm/store/reconcile.js.map +1 -1
  118. package/dist/esm/store/sqlite/lexical.js +1 -1
  119. package/dist/esm/store/sqlite/lexical.js.map +1 -1
  120. package/dist/esm/store/sqlite/store.js +0 -1
  121. package/dist/esm/store/sqlite/store.js.map +1 -1
  122. package/dist/esm/store/stages.d.ts +18 -0
  123. package/dist/esm/store/stages.js +63 -0
  124. package/dist/esm/store/stages.js.map +1 -0
  125. package/dist/esm/store/turso/store.js +1 -1
  126. package/dist/esm/store/turso/store.js.map +1 -1
  127. package/dist/esm/store/types.d.ts +2 -1
  128. package/dist/esm/store/types.js +0 -1
  129. package/dist/esm/store/types.js.map +1 -1
  130. package/dist/esm/text/segment.js +7 -5
  131. package/dist/esm/text/segment.js.map +1 -1
  132. package/dist/esm/watch.js +63 -38
  133. package/dist/esm/watch.js.map +1 -1
  134. package/dist/esm/workers/parse.d.ts +1 -0
  135. package/dist/esm/workers/parse.js +4 -1
  136. package/dist/esm/workers/parse.js.map +1 -1
  137. package/package.json +3 -3
  138. package/skills/sense/SKILL.md +1 -1
  139. package/skills/sense-setup/SKILL.md +1 -1
@@ -568,6 +568,7 @@ var DuckdbStatement = /*#__PURE__*/ function() {
568
568
  }();
569
569
  function createConnection(duckdb) {
570
570
  var conn = {
571
+ duckdb: duckdb,
571
572
  exec: function exec(sql) {
572
573
  return _async_to_generator(function() {
573
574
  return _ts_generator(this, function(_state) {
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/duckdb/connection.ts"],"sourcesContent":["import type { DuckDBConnection, DuckDBPreparedStatement, DuckDBValue } from '@duckdb/node-api';\nimport { withTransaction } from '../transaction.ts';\nimport type { Connection, RunResult, Statement } from '../types.ts';\nimport { rewriteBatch } from './batch.ts';\n\n// getRowObjectsJS returns INT64 columns as BigInt regardless of magnitude, while sqlite's small\n// ints are numbers and consumers assume number; in-range values convert here, out-of-range stays BigInt.\nconst MAX_SAFE = BigInt(Number.MAX_SAFE_INTEGER);\nexport function storeValueToJs(value: unknown): unknown {\n return typeof value === 'bigint' && value >= -MAX_SAFE && value <= MAX_SAFE ? Number(value) : value;\n}\nexport function storeRowToJs(row: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(row)) out[key] = storeValueToJs(value);\n return out;\n}\n\n// @duckdb/node-api only destroys a prepared statement when its connection closes, but a connection can stay open for a whole `sense watch` session.\n// Statement has no dispose (callers reuse one instance across several calls), so this FinalizationRegistry reclaims it once nothing references the wrapper.\nconst preparedFinalizer = new FinalizationRegistry<DuckDBPreparedStatement>((prepared) => {\n prepared.destroySync();\n});\n\n// Wraps one already-prepared DuckDB statement: prepare() is the only async step, so run/get/all rebind and\n// re-execute the same native statement, matching how callers like graph/traverse.ts's ring loop reuse one Statement across several calls.\nclass DuckdbStatement implements Statement {\n private prepared: DuckDBPreparedStatement;\n\n constructor(prepared: DuckDBPreparedStatement) {\n this.prepared = prepared;\n preparedFinalizer.register(this, prepared);\n }\n\n async run(...params: unknown[]): Promise<RunResult> {\n if (params.length > 0) this.prepared.bind(params as DuckDBValue[]);\n const result = await this.prepared.run();\n return { changes: result.rowsChanged, lastInsertRowid: 0 };\n }\n\n async get(...params: unknown[]): Promise<unknown> {\n const rows = await this.all(...params);\n return rows[0];\n }\n\n async all(...params: unknown[]): Promise<unknown[]> {\n if (params.length > 0) this.prepared.bind(params as DuckDBValue[]);\n const reader = await this.prepared.runAndReadAll();\n return (reader.getRowObjectsJS() as Array<Record<string, unknown>>).map(storeRowToJs);\n }\n\n async *iterate(...params: unknown[]): AsyncIterable<unknown> {\n // Never called on the portable Connection/Statement surface today (only Store.raw streams);\n // materializing keeps this a correct, if eager, AsyncIterable.\n yield* await this.all(...params);\n }\n\n columns(): Array<{ name: string }> {\n const out: Array<{ name: string }> = [];\n for (let i = 0; i < this.prepared.columnCount; i++) out.push({ name: this.prepared.columnName(i) });\n return out;\n }\n\n setReadBigInts(_enabled: boolean): void {\n // No-op: in-range ints are already numbers here (storeRowToJs converts what getRowObjectsJS\n // hands back as BigInt), so the node:sqlite throw-at-step-time problem does not exist.\n }\n}\n\nexport function createConnection(duckdb: DuckDBConnection): Connection {\n const conn: Connection = {\n async exec(sql: string): Promise<void> {\n await duckdb.run(sql);\n },\n async prepare(sql: string): Promise<Statement> {\n return new DuckdbStatement(await duckdb.prepare(sql));\n },\n // One crossing regardless of row count: rewriteBatch folds recognized shapes into a multi-row statement (batch.ts),\n // else falls back to a bind-and-run loop, one call either way. Joins the caller's transaction when there is one, else opens its own.\n async runBatch(sql: string, paramRows: unknown[][]): Promise<void> {\n if (paramRows.length === 0) return;\n await withTransaction(conn, async () => {\n const rewritten = rewriteBatch(sql, paramRows.length);\n if (rewritten) {\n const stmt = await duckdb.prepare(rewritten.sql);\n try {\n stmt.bind(paramRows.flat() as DuckDBValue[]);\n await stmt.run();\n } finally {\n stmt.destroySync();\n }\n return;\n }\n const stmt = await duckdb.prepare(sql);\n try {\n for (const row of paramRows) {\n stmt.bind(row as DuckDBValue[]);\n await stmt.run();\n }\n } finally {\n stmt.destroySync();\n }\n });\n },\n };\n return conn;\n}\n"],"names":["createConnection","storeRowToJs","storeValueToJs","MAX_SAFE","BigInt","Number","MAX_SAFE_INTEGER","value","row","out","Object","entries","key","preparedFinalizer","FinalizationRegistry","prepared","destroySync","DuckdbStatement","register","run","params","result","length","bind","changes","rowsChanged","lastInsertRowid","get","rows","all","reader","runAndReadAll","getRowObjectsJS","map","iterate","columns","i","columnCount","push","name","columnName","setReadBigInts","_enabled","duckdb","conn","exec","sql","prepare","runBatch","paramRows","withTransaction","rewritten","stmt","rewriteBatch","flat"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/duckdb/connection.ts"],"sourcesContent":["import type { DuckDBConnection, DuckDBPreparedStatement, DuckDBValue } from '@duckdb/node-api';\nimport { withTransaction } from '../transaction.ts';\nimport type { Connection, RunResult, Statement } from '../types.ts';\nimport { rewriteBatch } from './batch.ts';\n\n// getRowObjectsJS returns INT64 columns as BigInt regardless of magnitude, while sqlite's small\n// ints are numbers and consumers assume number; in-range values convert here, out-of-range stays BigInt.\nconst MAX_SAFE = BigInt(Number.MAX_SAFE_INTEGER);\nexport function storeValueToJs(value: unknown): unknown {\n return typeof value === 'bigint' && value >= -MAX_SAFE && value <= MAX_SAFE ? Number(value) : value;\n}\nexport function storeRowToJs(row: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(row)) out[key] = storeValueToJs(value);\n return out;\n}\n\n// @duckdb/node-api only destroys a prepared statement when its connection closes, but a connection can stay open for a whole `sense watch` session.\n// Statement has no dispose (callers reuse one instance across several calls), so this FinalizationRegistry reclaims it once nothing references the wrapper.\nconst preparedFinalizer = new FinalizationRegistry<DuckDBPreparedStatement>((prepared) => {\n prepared.destroySync();\n});\n\n// Wraps one already-prepared DuckDB statement: prepare() is the only async step, so run/get/all rebind and\n// re-execute the same native statement, matching how callers like graph/traverse.ts's ring loop reuse one Statement across several calls.\nclass DuckdbStatement implements Statement {\n private prepared: DuckDBPreparedStatement;\n\n constructor(prepared: DuckDBPreparedStatement) {\n this.prepared = prepared;\n preparedFinalizer.register(this, prepared);\n }\n\n async run(...params: unknown[]): Promise<RunResult> {\n if (params.length > 0) this.prepared.bind(params as DuckDBValue[]);\n const result = await this.prepared.run();\n return { changes: result.rowsChanged, lastInsertRowid: 0 };\n }\n\n async get(...params: unknown[]): Promise<unknown> {\n const rows = await this.all(...params);\n return rows[0];\n }\n\n async all(...params: unknown[]): Promise<unknown[]> {\n if (params.length > 0) this.prepared.bind(params as DuckDBValue[]);\n const reader = await this.prepared.runAndReadAll();\n return (reader.getRowObjectsJS() as Array<Record<string, unknown>>).map(storeRowToJs);\n }\n\n async *iterate(...params: unknown[]): AsyncIterable<unknown> {\n // Never called on the portable Connection/Statement surface today (only Store.raw streams);\n // materializing keeps this a correct, if eager, AsyncIterable.\n yield* await this.all(...params);\n }\n\n columns(): Array<{ name: string }> {\n const out: Array<{ name: string }> = [];\n for (let i = 0; i < this.prepared.columnCount; i++) out.push({ name: this.prepared.columnName(i) });\n return out;\n }\n\n setReadBigInts(_enabled: boolean): void {\n // No-op: in-range ints are already numbers here (storeRowToJs converts what getRowObjectsJS\n // hands back as BigInt), so the node:sqlite throw-at-step-time problem does not exist.\n }\n}\n\n// Adds the native DuckDBConnection to the portable Connection, so duckdb's own dialect code\n// (reconcile.ts's insertNew) can reach createAppender(); sqlite/turso have no such member.\nexport interface DuckdbConnection extends Connection {\n readonly duckdb: DuckDBConnection;\n}\n\nexport function createConnection(duckdb: DuckDBConnection): DuckdbConnection {\n const conn: DuckdbConnection = {\n duckdb,\n async exec(sql: string): Promise<void> {\n await duckdb.run(sql);\n },\n async prepare(sql: string): Promise<Statement> {\n return new DuckdbStatement(await duckdb.prepare(sql));\n },\n // One crossing regardless of row count: rewriteBatch folds recognized shapes into a multi-row statement (batch.ts),\n // else falls back to a bind-and-run loop, one call either way. Joins the caller's transaction when there is one, else opens its own.\n async runBatch(sql: string, paramRows: unknown[][]): Promise<void> {\n if (paramRows.length === 0) return;\n await withTransaction(conn, async () => {\n const rewritten = rewriteBatch(sql, paramRows.length);\n if (rewritten) {\n const stmt = await duckdb.prepare(rewritten.sql);\n try {\n stmt.bind(paramRows.flat() as DuckDBValue[]);\n await stmt.run();\n } finally {\n stmt.destroySync();\n }\n return;\n }\n const stmt = await duckdb.prepare(sql);\n try {\n for (const row of paramRows) {\n stmt.bind(row as DuckDBValue[]);\n await stmt.run();\n }\n } finally {\n stmt.destroySync();\n }\n });\n },\n };\n return conn;\n}\n"],"names":["createConnection","storeRowToJs","storeValueToJs","MAX_SAFE","BigInt","Number","MAX_SAFE_INTEGER","value","row","out","Object","entries","key","preparedFinalizer","FinalizationRegistry","prepared","destroySync","DuckdbStatement","register","run","params","result","length","bind","changes","rowsChanged","lastInsertRowid","get","rows","all","reader","runAndReadAll","getRowObjectsJS","map","iterate","columns","i","columnCount","push","name","columnName","setReadBigInts","_enabled","duckdb","conn","exec","sql","prepare","runBatch","paramRows","withTransaction","rewritten","stmt","rewriteBatch","flat"],"mappings":"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"}
@@ -9,8 +9,10 @@ Object.defineProperty(exports, "duckdbDialect", {
9
9
  }
10
10
  });
11
11
  var _errorsts = require("../../errors.js");
12
+ var _reconcilets = require("../reconcile.js");
12
13
  var _sharedts = require("../shared.js");
13
14
  var _lexicalts = require("./lexical.js");
15
+ var _nativets = require("./native.js");
14
16
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
15
17
  try {
16
18
  var info = gen[key](arg);
@@ -225,6 +227,107 @@ function addColumns(conn, names) {
225
227
  });
226
228
  })();
227
229
  }
230
+ // Appender path for rows that cannot conflict (reconcile.ts's `added`); no ON CONFLICT support, so
231
+ // alignment reads the table's own physical column order fresh -- `columns` omits feature-owned reserved columns (e.g. "_rank") that still exist on the table, and get appendDefault().
232
+ function insertNew(conn, table, columns, rows) {
233
+ return _async_to_generator(function() {
234
+ var variantValue, infoStmt, physicalColumns, rowIndexOf, native, appender, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, row, _iteratorNormalCompletion1, _didIteratorError1, _iteratorError1, _iterator1, _step1, name, idx, value;
235
+ return _ts_generator(this, function(_state) {
236
+ switch(_state.label){
237
+ case 0:
238
+ if (rows.length === 0) return [
239
+ 2
240
+ ];
241
+ return [
242
+ 4,
243
+ (0, _nativets.duckdbApi)()
244
+ ];
245
+ case 1:
246
+ variantValue = _state.sent().variantValue;
247
+ return [
248
+ 4,
249
+ conn.prepare("PRAGMA table_info(".concat((0, _sharedts.quoteIdent)(table), ")"))
250
+ ];
251
+ case 2:
252
+ infoStmt = _state.sent();
253
+ return [
254
+ 4,
255
+ infoStmt.all()
256
+ ];
257
+ case 3:
258
+ physicalColumns = _state.sent().map(function(c) {
259
+ return c.name;
260
+ });
261
+ rowIndexOf = new Map(columns.map(function(name, i) {
262
+ return [
263
+ name,
264
+ i
265
+ ];
266
+ }));
267
+ native = conn.duckdb;
268
+ return [
269
+ 4,
270
+ native.createAppender(table)
271
+ ];
272
+ case 4:
273
+ appender = _state.sent();
274
+ try {
275
+ _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
276
+ try {
277
+ for(_iterator = rows[Symbol.iterator](); !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
278
+ row = _step.value;
279
+ _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
280
+ try {
281
+ for(_iterator1 = physicalColumns[Symbol.iterator](); !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
282
+ name = _step1.value;
283
+ idx = rowIndexOf.get(name);
284
+ value = idx === undefined ? undefined : row[idx];
285
+ if (idx === undefined) appender.appendDefault();
286
+ else if (value === null || value === undefined) appender.appendNull();
287
+ else if (_reconcilets.CORE_FRONTMATTER_COLUMNS.has(name)) appender.appendValue(value);
288
+ else appender.appendVariant(variantValue(value));
289
+ }
290
+ } catch (err) {
291
+ _didIteratorError1 = true;
292
+ _iteratorError1 = err;
293
+ } finally{
294
+ try {
295
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
296
+ _iterator1.return();
297
+ }
298
+ } finally{
299
+ if (_didIteratorError1) {
300
+ throw _iteratorError1;
301
+ }
302
+ }
303
+ }
304
+ appender.endRow();
305
+ }
306
+ } catch (err) {
307
+ _didIteratorError = true;
308
+ _iteratorError = err;
309
+ } finally{
310
+ try {
311
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
312
+ _iterator.return();
313
+ }
314
+ } finally{
315
+ if (_didIteratorError) {
316
+ throw _iteratorError;
317
+ }
318
+ }
319
+ }
320
+ appender.flushSync();
321
+ } finally{
322
+ appender.closeSync();
323
+ }
324
+ return [
325
+ 2
326
+ ];
327
+ }
328
+ });
329
+ })();
330
+ }
228
331
  var duckdbDialect = {
229
332
  beginMode: function beginMode() {
230
333
  return 'BEGIN';
@@ -235,6 +338,7 @@ var duckdbDialect = {
235
338
  }
236
339
  },
237
340
  addColumns: addColumns,
238
- reconcileContent: reconcileContent
341
+ reconcileContent: reconcileContent,
342
+ insertNew: insertNew
239
343
  };
240
344
  /* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/duckdb/reconcile.ts"],"sourcesContent":["import { SenseError } from '../../errors.ts';\nimport type { ReconcileDelta } from '../../features/types.ts';\nimport type { ParsedDoc } from '../../scan/index.ts';\nimport { quoteIdent } from '../shared.ts';\nimport type { Connection, ReconcileDialect } from '../types.ts';\nimport { markContentStale } from './lexical.ts';\n\n// This store's dialect (types.ts's ReconcileDialect) for the shared orchestration in\n// store/reconcile.ts. `content` is a plain table, not FTS-virtual, so rows are maintained here\n// unconditionally; DuckDB's ALTER TABLE needs a declared type, so every dynamic frontmatter\n// column is VARIANT (holds mapValue()'s mixed JS types for one key across files).\n\n// No rowid coupling needed (unlike sqlite's content, which links to frontmatter's rowid):\n// `path` is content's own primary key, so this is a plain per-doc row.\nconst INSERT_CONTENT_SQL = `INSERT INTO content (\"path\", title, summary, text) VALUES (?, ?, ?, ?)`;\n\nfunction contentRow(doc: ParsedDoc): unknown[] {\n return [doc.relPath, doc.search.title, doc.search.summary, doc.search.text];\n}\n\n// No compile-time column cap in DuckDB (unlike SQLite's SQLITE_MAX_COLUMN); kept as a sanity fence anyway\n// so a runaway frontmatter generator fails with a clear message instead of an unbounded ALTER TABLE loop.\nconst MAX_FRONTMATTER_COLUMNS = 10_000;\n\nasync function reconcileContent(conn: Connection, touched: string[], docs: ParsedDoc[], _delta: ReconcileDelta): Promise<void> {\n if (touched.length > 0)\n await conn.runBatch(\n 'DELETE FROM content WHERE \"path\" = ?',\n touched.map((p) => [p])\n );\n if (docs.length > 0) await conn.runBatch(INSERT_CONTENT_SQL, docs.map(contentRow));\n // content changed: the fts index is rebuilt lazily, on the next lexical query that needs it,\n // not here (lexical.ts's FtsIndexState).\n markContentStale(conn);\n}\n\n// DuckDB rejects more than one ALTER command per statement (\"Parser Error: Only one ALTER\n// command per statement is supported\", measured), so every name's clause joins into one string\n// and runs as a single exec() -- one column-add \"leg\" through the driver instead of `names.length`.\n// VARIANT is the only type that can hold the mixed bigint/number/string/null shapes mapValue()\n// produces for one key across files.\nasync function addColumns(conn: Connection, names: string[]): Promise<void> {\n if (names.length === 0) return;\n await conn.exec(names.map((name) => `ALTER TABLE frontmatter ADD COLUMN ${quoteIdent(name)} VARIANT`).join('; '));\n}\n\nexport const duckdbDialect: ReconcileDialect = {\n beginMode: () => 'BEGIN',\n checkColumnLimit(count) {\n if (count > MAX_FRONTMATTER_COLUMNS) {\n throw new SenseError('COLUMN_LIMIT', `frontmatter would need ${count} columns, crossing this store's sanity limit (${MAX_FRONTMATTER_COLUMNS}). Narrow the presets' include globs so fewer/other files are indexed, or fix whatever is generating unbounded frontmatter keys.`);\n }\n },\n addColumns,\n reconcileContent,\n};\n"],"names":["duckdbDialect","INSERT_CONTENT_SQL","contentRow","doc","relPath","search","title","summary","text","MAX_FRONTMATTER_COLUMNS","reconcileContent","conn","touched","docs","_delta","length","runBatch","map","p","markContentStale","addColumns","names","exec","name","quoteIdent","join","beginMode","checkColumnLimit","count","SenseError"],"mappings":";;;;+BA8CaA;;;eAAAA;;;wBA9Cc;wBAGA;yBAEM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEjC,qFAAqF;AACrF,+FAA+F;AAC/F,4FAA4F;AAC5F,kFAAkF;AAElF,0FAA0F;AAC1F,uEAAuE;AACvE,IAAMC,qBAAqB;AAE3B,SAASC,WAAWC,GAAc;IAChC,OAAO;QAACA,IAAIC,OAAO;QAAED,IAAIE,MAAM,CAACC,KAAK;QAAEH,IAAIE,MAAM,CAACE,OAAO;QAAEJ,IAAIE,MAAM,CAACG,IAAI;KAAC;AAC7E;AAEA,0GAA0G;AAC1G,0GAA0G;AAC1G,IAAMC,0BAA0B;AAEhC,SAAeC,iBAAiBC,IAAgB,EAAEC,OAAiB,EAAEC,IAAiB,EAAEC,MAAsB;;;;;yBACxGF,CAAAA,QAAQG,MAAM,GAAG,CAAA,GAAjBH;;;;oBACF;;wBAAMD,KAAKK,QAAQ,CACjB,wCACAJ,QAAQK,GAAG,CAAC,SAACC;mCAAM;gCAACA;6BAAE;;;;oBAFxB;;;yBAIEL,CAAAA,KAAKE,MAAM,GAAG,CAAA,GAAdF;;;;oBAAiB;;wBAAMF,KAAKK,QAAQ,CAACf,oBAAoBY,KAAKI,GAAG,CAACf;;;oBAAjD;;;oBACrB,6FAA6F;oBAC7F,yCAAyC;oBACzCiB,IAAAA,2BAAgB,EAACR;;;;;;IACnB;;AAEA,0FAA0F;AAC1F,+FAA+F;AAC/F,oGAAoG;AACpG,+FAA+F;AAC/F,qCAAqC;AACrC,SAAeS,WAAWT,IAAgB,EAAEU,KAAe;;;;;oBACzD,IAAIA,MAAMN,MAAM,KAAK,GAAG;;;oBACxB;;wBAAMJ,KAAKW,IAAI,CAACD,MAAMJ,GAAG,CAAC,SAACM;mCAAS,AAAC,sCAAsD,OAAjBC,IAAAA,oBAAU,EAACD,OAAM;2BAAWE,IAAI,CAAC;;;oBAA3G;;;;;;IACF;;AAEO,IAAMzB,gBAAkC;IAC7C0B,WAAW,SAAXA;eAAiB;;IACjBC,kBAAAA,SAAAA,iBAAiBC,KAAK;QACpB,IAAIA,QAAQnB,yBAAyB;YACnC,MAAM,IAAIoB,oBAAU,CAAC,gBAAgB,AAAC,0BAA+EpB,OAAtDmB,OAAM,kDAAwE,OAAxBnB,yBAAwB;QAC/I;IACF;IACAW,YAAAA;IACAV,kBAAAA;AACF"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/duckdb/reconcile.ts"],"sourcesContent":["import type { DuckDBValue } from '@duckdb/node-api';\nimport { SenseError } from '../../errors.ts';\nimport type { ReconcileDelta } from '../../features/types.ts';\nimport type { ParsedDoc } from '../../scan/index.ts';\nimport { CORE_FRONTMATTER_COLUMNS } from '../reconcile.ts';\nimport { quoteIdent } from '../shared.ts';\nimport type { Connection, ReconcileDialect } from '../types.ts';\nimport type { DuckdbConnection } from './connection.ts';\nimport { markContentStale } from './lexical.ts';\nimport { duckdbApi } from './native.ts';\n\n// This store's dialect (types.ts's ReconcileDialect) for the shared orchestration in\n// store/reconcile.ts. `content` is a plain table, not FTS-virtual, so rows are maintained here\n// unconditionally; DuckDB's ALTER TABLE needs a declared type, so every dynamic frontmatter\n// column is VARIANT (holds mapValue()'s mixed JS types for one key across files).\n\n// No rowid coupling needed (unlike sqlite's content, which links to frontmatter's rowid):\n// `path` is content's own primary key, so this is a plain per-doc row.\nconst INSERT_CONTENT_SQL = `INSERT INTO content (\"path\", title, summary, text) VALUES (?, ?, ?, ?)`;\n\nfunction contentRow(doc: ParsedDoc): unknown[] {\n return [doc.relPath, doc.search.title, doc.search.summary, doc.search.text];\n}\n\n// No compile-time column cap in DuckDB (unlike SQLite's SQLITE_MAX_COLUMN); kept as a sanity fence anyway\n// so a runaway frontmatter generator fails with a clear message instead of an unbounded ALTER TABLE loop.\nconst MAX_FRONTMATTER_COLUMNS = 10_000;\n\nasync function reconcileContent(conn: Connection, touched: string[], docs: ParsedDoc[], _delta: ReconcileDelta): Promise<void> {\n if (touched.length > 0)\n await conn.runBatch(\n 'DELETE FROM content WHERE \"path\" = ?',\n touched.map((p) => [p])\n );\n if (docs.length > 0) await conn.runBatch(INSERT_CONTENT_SQL, docs.map(contentRow));\n // content changed: the fts index is rebuilt lazily, on the next lexical query that needs it,\n // not here (lexical.ts's FtsIndexState).\n markContentStale(conn);\n}\n\n// DuckDB rejects more than one ALTER command per statement (\"Parser Error: Only one ALTER\n// command per statement is supported\", measured), so every name's clause joins into one string\n// and runs as a single exec() -- one column-add \"leg\" through the driver instead of `names.length`.\n// VARIANT is the only type that can hold the mixed bigint/number/string/null shapes mapValue()\n// produces for one key across files.\nasync function addColumns(conn: Connection, names: string[]): Promise<void> {\n if (names.length === 0) return;\n await conn.exec(names.map((name) => `ALTER TABLE frontmatter ADD COLUMN ${quoteIdent(name)} VARIANT`).join('; '));\n}\n\n// Appender path for rows that cannot conflict (reconcile.ts's `added`); no ON CONFLICT support, so\n// alignment reads the table's own physical column order fresh -- `columns` omits feature-owned reserved columns (e.g. \"_rank\") that still exist on the table, and get appendDefault().\nasync function insertNew(conn: Connection, table: string, columns: string[], rows: unknown[][]): Promise<void> {\n if (rows.length === 0) return;\n const { variantValue } = await duckdbApi();\n const infoStmt = await conn.prepare(`PRAGMA table_info(${quoteIdent(table)})`);\n const physicalColumns = ((await infoStmt.all()) as Array<{ name: string }>).map((c) => c.name);\n const rowIndexOf = new Map(columns.map((name, i) => [name, i]));\n\n const native = (conn as DuckdbConnection).duckdb;\n const appender = await native.createAppender(table);\n try {\n for (const row of rows) {\n for (const name of physicalColumns) {\n const idx = rowIndexOf.get(name);\n const value = idx === undefined ? undefined : row[idx];\n if (idx === undefined) appender.appendDefault();\n else if (value === null || value === undefined) appender.appendNull();\n else if (CORE_FRONTMATTER_COLUMNS.has(name)) appender.appendValue(value as DuckDBValue);\n else appender.appendVariant(variantValue(value as DuckDBValue));\n }\n appender.endRow();\n }\n appender.flushSync();\n } finally {\n appender.closeSync();\n }\n}\n\nexport const duckdbDialect: ReconcileDialect = {\n beginMode: () => 'BEGIN',\n checkColumnLimit(count) {\n if (count > MAX_FRONTMATTER_COLUMNS) {\n throw new SenseError('COLUMN_LIMIT', `frontmatter would need ${count} columns, crossing this store's sanity limit (${MAX_FRONTMATTER_COLUMNS}). Narrow the presets' include globs so fewer/other files are indexed, or fix whatever is generating unbounded frontmatter keys.`);\n }\n },\n addColumns,\n reconcileContent,\n insertNew,\n};\n"],"names":["duckdbDialect","INSERT_CONTENT_SQL","contentRow","doc","relPath","search","title","summary","text","MAX_FRONTMATTER_COLUMNS","reconcileContent","conn","touched","docs","_delta","length","runBatch","map","p","markContentStale","addColumns","names","exec","name","quoteIdent","join","insertNew","table","columns","rows","variantValue","infoStmt","physicalColumns","rowIndexOf","native","appender","row","idx","value","duckdbApi","prepare","all","c","Map","i","duckdb","createAppender","get","undefined","appendDefault","appendNull","CORE_FRONTMATTER_COLUMNS","has","appendValue","appendVariant","endRow","flushSync","closeSync","beginMode","checkColumnLimit","count","SenseError"],"mappings":"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"}
@@ -1,15 +1,11 @@
1
1
  import type { ResolvedConfig } from '../config/index.js';
2
- import type { Builder } from './builder.js';
3
2
  import type { OpenResult } from './open.js';
4
3
  export declare function openStore(cfg: ResolvedConfig): Promise<OpenResult>;
5
- export declare function openStoreForWatch(cfg: ResolvedConfig): Promise<OpenResult & {
6
- builder: Builder;
7
- }>;
8
- export declare function requireWatchConcurrency(cfg: ResolvedConfig): void;
9
4
  export { clearCache } from './cache.js';
10
5
  export type { OpenResult } from './open.js';
11
6
  export { docCount } from './open.js';
12
7
  export { getMeta, setMeta } from './shared.js';
13
8
  export { DB_FILENAME, SCHEMA_VERSION } from './sqlite/open.js';
9
+ export type { Stages } from './stages.js';
14
10
  export type { Capability, Connection, DocumentStore, LexicalHit, LexicalIndex, LexicalQueryOptions, RawStatement, RunResult, SqlSession, Statement, Store, VectorCandidate, VectorSimilar, VectorStore, VectorWriteRow } from './types.js';
15
11
  export { CAPABILITY_NAMES } from './types.js';
@@ -1,15 +1,11 @@
1
1
  import type { ResolvedConfig } from '../config/index.js';
2
- import type { Builder } from './builder.js';
3
2
  import type { OpenResult } from './open.js';
4
3
  export declare function openStore(cfg: ResolvedConfig): Promise<OpenResult>;
5
- export declare function openStoreForWatch(cfg: ResolvedConfig): Promise<OpenResult & {
6
- builder: Builder;
7
- }>;
8
- export declare function requireWatchConcurrency(cfg: ResolvedConfig): void;
9
4
  export { clearCache } from './cache.js';
10
5
  export type { OpenResult } from './open.js';
11
6
  export { docCount } from './open.js';
12
7
  export { getMeta, setMeta } from './shared.js';
13
8
  export { DB_FILENAME, SCHEMA_VERSION } from './sqlite/open.js';
9
+ export type { Stages } from './stages.js';
14
10
  export type { Capability, Connection, DocumentStore, LexicalHit, LexicalIndex, LexicalQueryOptions, RawStatement, RunResult, SqlSession, Statement, Store, VectorCandidate, VectorSimilar, VectorStore, VectorWriteRow } from './types.js';
15
11
  export { CAPABILITY_NAMES } from './types.js';
@@ -15,16 +15,16 @@ _export(exports, {
15
15
  return _typests.CAPABILITY_NAMES;
16
16
  },
17
17
  get DB_FILENAME () {
18
- return _opents2.DB_FILENAME;
18
+ return _opents1.DB_FILENAME;
19
19
  },
20
20
  get SCHEMA_VERSION () {
21
- return _opents2.SCHEMA_VERSION;
21
+ return _opents1.SCHEMA_VERSION;
22
22
  },
23
23
  get clearCache () {
24
24
  return _cachets.clearCache;
25
25
  },
26
26
  get docCount () {
27
- return _opents1.docCount;
27
+ return _opents3.docCount;
28
28
  },
29
29
  get getMeta () {
30
30
  return _sharedts.getMeta;
@@ -32,12 +32,6 @@ _export(exports, {
32
32
  get openStore () {
33
33
  return openStore;
34
34
  },
35
- get openStoreForWatch () {
36
- return openStoreForWatch;
37
- },
38
- get requireWatchConcurrency () {
39
- return requireWatchConcurrency;
40
- },
41
35
  get setMeta () {
42
36
  return _sharedts.setMeta;
43
37
  }
@@ -46,12 +40,12 @@ var _indexts = require("../config/index.js");
46
40
  var _errorsts = require("../errors.js");
47
41
  var _opents = require("./duckdb/open.js");
48
42
  var _storets = require("./duckdb/store.js");
49
- var _opents1 = require("./open.js");
50
- var _opents2 = require("./sqlite/open.js");
43
+ var _opents1 = require("./sqlite/open.js");
51
44
  var _storets1 = require("./sqlite/store.js");
52
- var _opents3 = require("./turso/open.js");
45
+ var _opents2 = require("./turso/open.js");
53
46
  var _storets2 = require("./turso/store.js");
54
47
  var _cachets = require("./cache.js");
48
+ var _opents3 = require("./open.js");
55
49
  var _sharedts = require("./shared.js");
56
50
  var _typests = require("./types.js");
57
51
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
@@ -184,24 +178,15 @@ function _ts_generator(thisArg, body) {
184
178
  var REGISTRY = {
185
179
  sqlite: {
186
180
  capabilities: _storets1.CAPABILITIES,
187
- open: _opents2.openSqlite,
188
- openForWatch: function openForWatch(cfg) {
189
- return (0, _opents1.openWithBuilder)(cfg, _opents2.sqliteOpenDialect);
190
- }
181
+ open: _opents1.openSqlite
191
182
  },
192
183
  duckdb: {
193
184
  capabilities: _storets.CAPABILITIES,
194
- open: _opents.openDuckdb,
195
- openForWatch: function openForWatch(cfg) {
196
- return (0, _opents1.openWithBuilder)(cfg, _opents.duckdbOpenDialect);
197
- }
185
+ open: _opents.openDuckdb
198
186
  },
199
187
  turso: {
200
188
  capabilities: _storets2.CAPABILITIES,
201
- open: _opents3.openTurso,
202
- openForWatch: function openForWatch(cfg) {
203
- return (0, _opents1.openWithBuilder)(cfg, _opents3.tursoOpenDialect);
204
- }
189
+ open: _opents2.openTurso
205
190
  }
206
191
  };
207
192
  function entryFor(name) {
@@ -227,26 +212,4 @@ function openStore(cfg) {
227
212
  });
228
213
  })();
229
214
  }
230
- function openStoreForWatch(cfg) {
231
- return _async_to_generator(function() {
232
- var name, entry;
233
- return _ts_generator(this, function(_state) {
234
- name = (0, _indexts.storeName)(cfg);
235
- entry = entryFor(name);
236
- if ((0, _indexts.anyPresetEmbeds)(cfg) && !entry.capabilities.has('vectors')) {
237
- throw new _errorsts.SenseError('STORE_CAPABILITY_MISSING', 'store "'.concat(name, '" does not implement "vectors" in this build, but this config\'s "embed" block is in use by at least one preset; remove or narrow it, or set "store" to a store that supports vectors (sqlite)'));
238
- }
239
- return [
240
- 2,
241
- entry.openForWatch(cfg)
242
- ];
243
- });
244
- })();
245
- }
246
- function requireWatchConcurrency(cfg) {
247
- var name = (0, _indexts.storeName)(cfg);
248
- if (!entryFor(name).capabilities.has('watch-concurrency')) {
249
- throw new _errorsts.SenseError('STORE_CAPABILITY_MISSING', 'store "'.concat(name, '" does not implement "watch-concurrency" in this build; sense watch holds the store open for its whole run, and this store locks the cache file, so every other command on this tree would fail to open; set "store" to "sqlite" in sense.config.json'));
250
- }
251
- }
252
215
  /* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/index.ts"],"sourcesContent":["// Rows -> a backing store: registry + openStore(cfg). Parsing lives in scan.ts; everything\n// beyond frontmatter + content lives in src/features/.\n\nimport type { ResolvedConfig, StoreName } from '../config/index.ts';\nimport { anyPresetEmbeds, storeName } from '../config/index.ts';\nimport { SenseError } from '../errors.ts';\nimport type { Builder } from './builder.ts';\nimport { duckdbOpenDialect, openDuckdb } from './duckdb/open.ts';\nimport { CAPABILITIES as DUCKDB_CAPABILITIES } from './duckdb/store.ts';\nimport type { OpenResult } from './open.ts';\nimport { openWithBuilder } from './open.ts';\nimport { openSqlite, sqliteOpenDialect } from './sqlite/open.ts';\nimport { CAPABILITIES as SQLITE_CAPABILITIES } from './sqlite/store.ts';\nimport { openTurso, tursoOpenDialect } from './turso/open.ts';\nimport { CAPABILITIES as TURSO_CAPABILITIES } from './turso/store.ts';\nimport type { Capability } from './types.ts';\n\ninterface StoreEntry {\n capabilities: ReadonlySet<Capability>;\n open: (cfg: ResolvedConfig) => Promise<OpenResult>;\n // Same open, but keeps the builder's parse pool alive and hands it back: only a watcher, which\n // reconciles repeatedly on the same connection, needs this.\n openForWatch: (cfg: ResolvedConfig) => Promise<OpenResult & { builder: Builder }>;\n}\n\n// Capabilities are checked against the registry entry before opening (no wasted connect/reconcile\n// work for a config that cannot be satisfied), then the store itself opens.\nconst REGISTRY: Record<StoreName, StoreEntry> = {\n sqlite: { capabilities: SQLITE_CAPABILITIES, open: openSqlite, openForWatch: (cfg) => openWithBuilder(cfg, sqliteOpenDialect) },\n duckdb: { capabilities: DUCKDB_CAPABILITIES, open: openDuckdb, openForWatch: (cfg) => openWithBuilder(cfg, duckdbOpenDialect) },\n turso: { capabilities: TURSO_CAPABILITIES, open: openTurso, openForWatch: (cfg) => openWithBuilder(cfg, tursoOpenDialect) },\n};\n\nfunction entryFor(name: StoreName): StoreEntry {\n const entry = REGISTRY[name];\n if (!entry) throw new SenseError('STORE_UNKNOWN', `unknown backing store \"${name}\"; available: ${Object.keys(REGISTRY).join(', ')}`);\n return entry;\n}\n\nexport async function openStore(cfg: ResolvedConfig): Promise<OpenResult> {\n const name = storeName(cfg);\n const entry = entryFor(name);\n\n // The one unambiguous, config-level capability need: an embed block some preset actually uses\n // for vectors. Lexical search has no such signal at this level (every preset defaults to \"words\"), so a store lacking it fails loudly at first use.\n if (anyPresetEmbeds(cfg) && !entry.capabilities.has('vectors')) {\n throw new SenseError('STORE_CAPABILITY_MISSING', `store \"${name}\" does not implement \"vectors\" in this build, but this config's \"embed\" block is in use by at least one preset; remove or narrow it, or set \"store\" to a store that supports vectors (sqlite)`);\n }\n\n return entry.open(cfg);\n}\n\n// Same capability-checked open as openStore, but for a caller (only src/watch.ts) that must\n// reconcile again later: keeps the builder's pool warm and hands it back instead of closing it.\nexport async function openStoreForWatch(cfg: ResolvedConfig): Promise<OpenResult & { builder: Builder }> {\n const name = storeName(cfg);\n const entry = entryFor(name);\n\n if (anyPresetEmbeds(cfg) && !entry.capabilities.has('vectors')) {\n throw new SenseError('STORE_CAPABILITY_MISSING', `store \"${name}\" does not implement \"vectors\" in this build, but this config's \"embed\" block is in use by at least one preset; remove or narrow it, or set \"store\" to a store that supports vectors (sqlite)`);\n }\n\n return entry.openForWatch(cfg);\n}\n\n// watch keeps its connection open for the run, so a file-locking store would fail every\n// other command on the tree; check before open, as openStore does for \"vectors\".\nexport function requireWatchConcurrency(cfg: ResolvedConfig): void {\n const name = storeName(cfg);\n if (!entryFor(name).capabilities.has('watch-concurrency')) {\n throw new SenseError('STORE_CAPABILITY_MISSING', `store \"${name}\" does not implement \"watch-concurrency\" in this build; sense watch holds the store open for its whole run, and this store locks the cache file, so every other command on this tree would fail to open; set \"store\" to \"sqlite\" in sense.config.json`);\n }\n}\n\nexport { clearCache } from './cache.ts';\nexport type { OpenResult } from './open.ts';\nexport { docCount } from './open.ts';\nexport { getMeta, setMeta } from './shared.ts';\nexport { DB_FILENAME, SCHEMA_VERSION } from './sqlite/open.ts';\nexport type { Capability, Connection, DocumentStore, LexicalHit, LexicalIndex, LexicalQueryOptions, RawStatement, RunResult, SqlSession, Statement, Store, VectorCandidate, VectorSimilar, VectorStore, VectorWriteRow } from './types.ts';\nexport { CAPABILITY_NAMES } from './types.ts';\n"],"names":["CAPABILITY_NAMES","DB_FILENAME","SCHEMA_VERSION","clearCache","docCount","getMeta","openStore","openStoreForWatch","requireWatchConcurrency","setMeta","REGISTRY","sqlite","capabilities","SQLITE_CAPABILITIES","open","openSqlite","openForWatch","cfg","openWithBuilder","sqliteOpenDialect","duckdb","DUCKDB_CAPABILITIES","openDuckdb","duckdbOpenDialect","turso","TURSO_CAPABILITIES","openTurso","tursoOpenDialect","entryFor","name","entry","SenseError","Object","keys","join","storeName","anyPresetEmbeds","has"],"mappings":"AAAA,2FAA2F;AAC3F,uDAAuD;;;;;;;;;;;;QA+E9CA;eAAAA,yBAAgB;;QAFhBC;eAAAA,oBAAW;;QAAEC;eAAAA,uBAAc;;QAJ3BC;eAAAA,mBAAU;;QAEVC;eAAAA,iBAAQ;;QACRC;eAAAA,iBAAO;;QAtCMC;eAAAA;;QAeAC;eAAAA;;QAaNC;eAAAA;;QAUEC;eAAAA,iBAAO;;;uBAzEkB;wBAChB;sBAEmB;uBACM;uBAEpB;uBACc;wBACM;uBACR;wBACO;uBA4DxB;wBAGM;uBAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAvDjC,kGAAkG;AAClG,4EAA4E;AAC5E,IAAMC,WAA0C;IAC9CC,QAAQ;QAAEC,cAAcC,sBAAmB;QAAEC,MAAMC,mBAAU;QAAEC,cAAc,SAAdA,aAAeC;mBAAQC,IAAAA,wBAAe,EAACD,KAAKE,0BAAiB;;IAAE;IAC9HC,QAAQ;QAAER,cAAcS,qBAAmB;QAAEP,MAAMQ,kBAAU;QAAEN,cAAc,SAAdA,aAAeC;mBAAQC,IAAAA,wBAAe,EAACD,KAAKM,yBAAiB;;IAAE;IAC9HC,OAAO;QAAEZ,cAAca,sBAAkB;QAAEX,MAAMY,kBAAS;QAAEV,cAAc,SAAdA,aAAeC;mBAAQC,IAAAA,wBAAe,EAACD,KAAKU,yBAAgB;;IAAE;AAC5H;AAEA,SAASC,SAASC,IAAe;IAC/B,IAAMC,QAAQpB,QAAQ,CAACmB,KAAK;IAC5B,IAAI,CAACC,OAAO,MAAM,IAAIC,oBAAU,CAAC,iBAAiB,AAAC,0BAA8CC,OAArBH,MAAK,kBAAiD,OAAjCG,OAAOC,IAAI,CAACvB,UAAUwB,IAAI,CAAC;IAC5H,OAAOJ;AACT;AAEO,SAAexB,UAAUW,GAAmB;;YAC3CY,MACAC;;YADAD,OAAOM,IAAAA,kBAAS,EAAClB;YACjBa,QAAQF,SAASC;YAEvB,8FAA8F;YAC9F,oJAAoJ;YACpJ,IAAIO,IAAAA,wBAAe,EAACnB,QAAQ,CAACa,MAAMlB,YAAY,CAACyB,GAAG,CAAC,YAAY;gBAC9D,MAAM,IAAIN,oBAAU,CAAC,4BAA4B,AAAC,UAAc,OAALF,MAAK;YAClE;YAEA;;gBAAOC,MAAMhB,IAAI,CAACG;;;IACpB;;AAIO,SAAeV,kBAAkBU,GAAmB;;YACnDY,MACAC;;YADAD,OAAOM,IAAAA,kBAAS,EAAClB;YACjBa,QAAQF,SAASC;YAEvB,IAAIO,IAAAA,wBAAe,EAACnB,QAAQ,CAACa,MAAMlB,YAAY,CAACyB,GAAG,CAAC,YAAY;gBAC9D,MAAM,IAAIN,oBAAU,CAAC,4BAA4B,AAAC,UAAc,OAALF,MAAK;YAClE;YAEA;;gBAAOC,MAAMd,YAAY,CAACC;;;IAC5B;;AAIO,SAAST,wBAAwBS,GAAmB;IACzD,IAAMY,OAAOM,IAAAA,kBAAS,EAAClB;IACvB,IAAI,CAACW,SAASC,MAAMjB,YAAY,CAACyB,GAAG,CAAC,sBAAsB;QACzD,MAAM,IAAIN,oBAAU,CAAC,4BAA4B,AAAC,UAAc,OAALF,MAAK;IAClE;AACF"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/index.ts"],"sourcesContent":["// Rows -> a backing store: registry + openStore(cfg). Parsing lives in scan.ts; everything\n// beyond frontmatter + content lives in src/features/.\n\nimport type { ResolvedConfig, StoreName } from '../config/index.ts';\nimport { anyPresetEmbeds, storeName } from '../config/index.ts';\nimport { SenseError } from '../errors.ts';\nimport { openDuckdb } from './duckdb/open.ts';\nimport { CAPABILITIES as DUCKDB_CAPABILITIES } from './duckdb/store.ts';\nimport type { OpenResult } from './open.ts';\nimport { openSqlite } from './sqlite/open.ts';\nimport { CAPABILITIES as SQLITE_CAPABILITIES } from './sqlite/store.ts';\nimport { openTurso } from './turso/open.ts';\nimport { CAPABILITIES as TURSO_CAPABILITIES } from './turso/store.ts';\nimport type { Capability } from './types.ts';\n\ninterface StoreEntry {\n capabilities: ReadonlySet<Capability>;\n open: (cfg: ResolvedConfig) => Promise<OpenResult>;\n}\n\n// Capabilities are checked against the registry entry before opening (no wasted connect/reconcile\n// work for a config that cannot be satisfied), then the store itself opens.\nconst REGISTRY: Record<StoreName, StoreEntry> = {\n sqlite: { capabilities: SQLITE_CAPABILITIES, open: openSqlite },\n duckdb: { capabilities: DUCKDB_CAPABILITIES, open: openDuckdb },\n turso: { capabilities: TURSO_CAPABILITIES, open: openTurso },\n};\n\nfunction entryFor(name: StoreName): StoreEntry {\n const entry = REGISTRY[name];\n if (!entry) throw new SenseError('STORE_UNKNOWN', `unknown backing store \"${name}\"; available: ${Object.keys(REGISTRY).join(', ')}`);\n return entry;\n}\n\nexport async function openStore(cfg: ResolvedConfig): Promise<OpenResult> {\n const name = storeName(cfg);\n const entry = entryFor(name);\n\n // The one unambiguous, config-level capability need: an embed block some preset actually uses\n // for vectors. Lexical search has no such signal at this level (every preset defaults to \"words\"), so a store lacking it fails loudly at first use.\n if (anyPresetEmbeds(cfg) && !entry.capabilities.has('vectors')) {\n throw new SenseError('STORE_CAPABILITY_MISSING', `store \"${name}\" does not implement \"vectors\" in this build, but this config's \"embed\" block is in use by at least one preset; remove or narrow it, or set \"store\" to a store that supports vectors (sqlite)`);\n }\n\n return entry.open(cfg);\n}\n\nexport { clearCache } from './cache.ts';\nexport type { OpenResult } from './open.ts';\nexport { docCount } from './open.ts';\nexport { getMeta, setMeta } from './shared.ts';\nexport { DB_FILENAME, SCHEMA_VERSION } from './sqlite/open.ts';\nexport type { Stages } from './stages.ts';\nexport type { Capability, Connection, DocumentStore, LexicalHit, LexicalIndex, LexicalQueryOptions, RawStatement, RunResult, SqlSession, Statement, Store, VectorCandidate, VectorSimilar, VectorStore, VectorWriteRow } from './types.ts';\nexport { CAPABILITY_NAMES } from './types.ts';\n"],"names":["CAPABILITY_NAMES","DB_FILENAME","SCHEMA_VERSION","clearCache","docCount","getMeta","openStore","setMeta","REGISTRY","sqlite","capabilities","SQLITE_CAPABILITIES","open","openSqlite","duckdb","DUCKDB_CAPABILITIES","openDuckdb","turso","TURSO_CAPABILITIES","openTurso","entryFor","name","entry","SenseError","Object","keys","join","cfg","storeName","anyPresetEmbeds","has"],"mappings":"AAAA,2FAA2F;AAC3F,uDAAuD;;;;;;;;;;;;QAqD9CA;eAAAA,yBAAgB;;QAHhBC;eAAAA,oBAAW;;QAAEC;eAAAA,uBAAc;;QAJ3BC;eAAAA,mBAAU;;QAEVC;eAAAA,iBAAQ;;QACRC;eAAAA,iBAAO;;QAhBMC;eAAAA;;QAgBJC;eAAAA,iBAAO;;;uBA9CkB;wBAChB;sBACA;uBACyB;uBAEzB;wBACyB;uBAC1B;wBACyB;uBAmCxB;uBAEF;wBACQ;uBAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAlCjC,kGAAkG;AAClG,4EAA4E;AAC5E,IAAMC,WAA0C;IAC9CC,QAAQ;QAAEC,cAAcC,sBAAmB;QAAEC,MAAMC,mBAAU;IAAC;IAC9DC,QAAQ;QAAEJ,cAAcK,qBAAmB;QAAEH,MAAMI,kBAAU;IAAC;IAC9DC,OAAO;QAAEP,cAAcQ,sBAAkB;QAAEN,MAAMO,kBAAS;IAAC;AAC7D;AAEA,SAASC,SAASC,IAAe;IAC/B,IAAMC,QAAQd,QAAQ,CAACa,KAAK;IAC5B,IAAI,CAACC,OAAO,MAAM,IAAIC,oBAAU,CAAC,iBAAiB,AAAC,0BAA8CC,OAArBH,MAAK,kBAAiD,OAAjCG,OAAOC,IAAI,CAACjB,UAAUkB,IAAI,CAAC;IAC5H,OAAOJ;AACT;AAEO,SAAehB,UAAUqB,GAAmB;;YAC3CN,MACAC;;YADAD,OAAOO,IAAAA,kBAAS,EAACD;YACjBL,QAAQF,SAASC;YAEvB,8FAA8F;YAC9F,oJAAoJ;YACpJ,IAAIQ,IAAAA,wBAAe,EAACF,QAAQ,CAACL,MAAMZ,YAAY,CAACoB,GAAG,CAAC,YAAY;gBAC9D,MAAM,IAAIP,oBAAU,CAAC,4BAA4B,AAAC,UAAc,OAALF,MAAK;YAClE;YAEA;;gBAAOC,MAAMV,IAAI,CAACe;;;IACpB"}
@@ -0,0 +1,2 @@
1
+ export declare function recordLockWaitMs(baseDir: string, ms: number): void;
2
+ export declare function lockWaitBudgetMs(baseDir: string): number;
@@ -0,0 +1,2 @@
1
+ export declare function recordLockWaitMs(baseDir: string, ms: number): void;
2
+ export declare function lockWaitBudgetMs(baseDir: string): number;
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: Object.getOwnPropertyDescriptor(all, name).get
9
+ });
10
+ }
11
+ _export(exports, {
12
+ get lockWaitBudgetMs () {
13
+ return lockWaitBudgetMs;
14
+ },
15
+ get recordLockWaitMs () {
16
+ return recordLockWaitMs;
17
+ }
18
+ });
19
+ var _nodefs = require("node:fs");
20
+ var _nodepath = require("node:path");
21
+ var _indexts = require("../config/index.js");
22
+ // duckdb/turso lock the cache file exclusively, so a waiter can't connect and read reconcile_max_ms
23
+ // from meta; this sidecar is plain fs, readable while locked. Same derivation as busy_timeout (open.ts).
24
+ var SIDECAR_FILENAME = 'lock-wait.json';
25
+ var FLOOR_MS = 5000;
26
+ var CEILING_MS = 600000;
27
+ function sidecarPath(baseDir) {
28
+ return (0, _nodepath.join)(baseDir, _indexts.STATE_DIR, SIDECAR_FILENAME);
29
+ }
30
+ function readRecordedMs(baseDir) {
31
+ try {
32
+ var raw = JSON.parse((0, _nodefs.readFileSync)(sidecarPath(baseDir), 'utf8'));
33
+ return typeof raw.reconcile_max_ms === 'number' ? raw.reconcile_max_ms : 0;
34
+ } catch (unused) {
35
+ return 0;
36
+ }
37
+ }
38
+ function recordLockWaitMs(baseDir, ms) {
39
+ if (ms <= readRecordedMs(baseDir)) return;
40
+ try {
41
+ (0, _nodefs.writeFileSync)(sidecarPath(baseDir), JSON.stringify({
42
+ reconcile_max_ms: ms
43
+ }));
44
+ } catch (unused) {
45
+ // Best-effort: a write failure here only narrows the next waiter's budget back to the floor.
46
+ }
47
+ }
48
+ function lockWaitBudgetMs(baseDir) {
49
+ return Math.min(Math.max(FLOOR_MS, 3 * readRecordedMs(baseDir)), CEILING_MS);
50
+ }
51
+ /* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/lock-wait.ts"],"sourcesContent":["import { readFileSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { STATE_DIR } from '../config/index.ts';\n\n// duckdb/turso lock the cache file exclusively, so a waiter can't connect and read reconcile_max_ms\n// from meta; this sidecar is plain fs, readable while locked. Same derivation as busy_timeout (open.ts).\nconst SIDECAR_FILENAME = 'lock-wait.json';\nconst FLOOR_MS = 5_000;\nconst CEILING_MS = 600_000;\n\nfunction sidecarPath(baseDir: string): string {\n return join(baseDir, STATE_DIR, SIDECAR_FILENAME);\n}\n\nfunction readRecordedMs(baseDir: string): number {\n try {\n const raw = JSON.parse(readFileSync(sidecarPath(baseDir), 'utf8'));\n return typeof raw.reconcile_max_ms === 'number' ? raw.reconcile_max_ms : 0;\n } catch {\n return 0;\n }\n}\n\n// Called after every reconcile's write transaction, every store alike, so a fresh duckdb/turso\n// tree starts building this the first time anything writes.\nexport function recordLockWaitMs(baseDir: string, ms: number): void {\n if (ms <= readRecordedMs(baseDir)) return;\n try {\n writeFileSync(sidecarPath(baseDir), JSON.stringify({ reconcile_max_ms: ms }));\n } catch {\n // Best-effort: a write failure here only narrows the next waiter's budget back to the floor.\n }\n}\n\n// 3x the largest reconcile this tree has recorded, floored and capped -- a waiter outlasts a\n// real reconcile and still fails behind a hung one.\nexport function lockWaitBudgetMs(baseDir: string): number {\n return Math.min(Math.max(FLOOR_MS, 3 * readRecordedMs(baseDir)), CEILING_MS);\n}\n"],"names":["lockWaitBudgetMs","recordLockWaitMs","SIDECAR_FILENAME","FLOOR_MS","CEILING_MS","sidecarPath","baseDir","join","STATE_DIR","readRecordedMs","raw","JSON","parse","readFileSync","reconcile_max_ms","ms","writeFileSync","stringify","Math","min","max"],"mappings":";;;;;;;;;;;QAoCgBA;eAAAA;;QAXAC;eAAAA;;;sBAzB4B;wBACvB;uBACK;AAE1B,oGAAoG;AACpG,yGAAyG;AACzG,IAAMC,mBAAmB;AACzB,IAAMC,WAAW;AACjB,IAAMC,aAAa;AAEnB,SAASC,YAAYC,OAAe;IAClC,OAAOC,IAAAA,cAAI,EAACD,SAASE,kBAAS,EAAEN;AAClC;AAEA,SAASO,eAAeH,OAAe;IACrC,IAAI;QACF,IAAMI,MAAMC,KAAKC,KAAK,CAACC,IAAAA,oBAAY,EAACR,YAAYC,UAAU;QAC1D,OAAO,OAAOI,IAAII,gBAAgB,KAAK,WAAWJ,IAAII,gBAAgB,GAAG;IAC3E,EAAE,eAAM;QACN,OAAO;IACT;AACF;AAIO,SAASb,iBAAiBK,OAAe,EAAES,EAAU;IAC1D,IAAIA,MAAMN,eAAeH,UAAU;IACnC,IAAI;QACFU,IAAAA,qBAAa,EAACX,YAAYC,UAAUK,KAAKM,SAAS,CAAC;YAAEH,kBAAkBC;QAAG;IAC5E,EAAE,eAAM;IACN,6FAA6F;IAC/F;AACF;AAIO,SAASf,iBAAiBM,OAAe;IAC9C,OAAOY,KAAKC,GAAG,CAACD,KAAKE,GAAG,CAACjB,UAAU,IAAIM,eAAeH,WAAWF;AACnE"}
@@ -1,5 +1,5 @@
1
1
  import type { ResolvedConfig } from '../config/index.js';
2
- import type { Builder } from './builder.js';
2
+ import type { Stages } from './stages.js';
3
3
  import type { OpenDialect, Store } from './types.js';
4
4
  export interface OpenResult {
5
5
  store: Store;
@@ -7,9 +7,7 @@ export interface OpenResult {
7
7
  dbPath: string;
8
8
  parsed: number;
9
9
  warnings: string[];
10
+ stages: Stages;
10
11
  }
11
12
  export declare function openWithDialect<Handle>(cfg: ResolvedConfig, dialect: OpenDialect<Handle>): Promise<OpenResult>;
12
- export declare function openWithBuilder<Handle>(cfg: ResolvedConfig, dialect: OpenDialect<Handle>): Promise<OpenResult & {
13
- builder: Builder;
14
- }>;
15
13
  export declare function docCount(store: Store): Promise<number>;
@@ -1,5 +1,5 @@
1
1
  import type { ResolvedConfig } from '../config/index.js';
2
- import type { Builder } from './builder.js';
2
+ import type { Stages } from './stages.js';
3
3
  import type { OpenDialect, Store } from './types.js';
4
4
  export interface OpenResult {
5
5
  store: Store;
@@ -7,9 +7,7 @@ export interface OpenResult {
7
7
  dbPath: string;
8
8
  parsed: number;
9
9
  warnings: string[];
10
+ stages: Stages;
10
11
  }
11
12
  export declare function openWithDialect<Handle>(cfg: ResolvedConfig, dialect: OpenDialect<Handle>): Promise<OpenResult>;
12
- export declare function openWithBuilder<Handle>(cfg: ResolvedConfig, dialect: OpenDialect<Handle>): Promise<OpenResult & {
13
- builder: Builder;
14
- }>;
15
13
  export declare function docCount(store: Store): Promise<number>;