sensemaking 0.21.1 → 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 (104) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/chunk/group.js +13 -9
  3. package/dist/cjs/chunk/group.js.map +1 -1
  4. package/dist/cjs/commands/search.js +1 -1
  5. package/dist/cjs/commands/search.js.map +1 -1
  6. package/dist/cjs/index.d.cts +1 -1
  7. package/dist/cjs/index.d.ts +1 -1
  8. package/dist/cjs/index.js.map +1 -1
  9. package/dist/cjs/scan/pool.d.cts +1 -0
  10. package/dist/cjs/scan/pool.d.ts +1 -0
  11. package/dist/cjs/scan/pool.js +2 -1
  12. package/dist/cjs/scan/pool.js.map +1 -1
  13. package/dist/cjs/scan/reparse.d.cts +1 -0
  14. package/dist/cjs/scan/reparse.d.ts +1 -0
  15. package/dist/cjs/scan/reparse.js +6 -3
  16. package/dist/cjs/scan/reparse.js.map +1 -1
  17. package/dist/cjs/store/builder.d.cts +2 -0
  18. package/dist/cjs/store/builder.d.ts +2 -0
  19. package/dist/cjs/store/builder.js.map +1 -1
  20. package/dist/cjs/store/index.d.cts +1 -5
  21. package/dist/cjs/store/index.d.ts +1 -5
  22. package/dist/cjs/store/index.js +9 -46
  23. package/dist/cjs/store/index.js.map +1 -1
  24. package/dist/cjs/store/lock-wait.d.cts +2 -0
  25. package/dist/cjs/store/lock-wait.d.ts +2 -0
  26. package/dist/cjs/store/lock-wait.js +51 -0
  27. package/dist/cjs/store/lock-wait.js.map +1 -0
  28. package/dist/cjs/store/open.d.cts +2 -4
  29. package/dist/cjs/store/open.d.ts +2 -4
  30. package/dist/cjs/store/open.js +29 -66
  31. package/dist/cjs/store/open.js.map +1 -1
  32. package/dist/cjs/store/reconcile.d.cts +2 -0
  33. package/dist/cjs/store/reconcile.d.ts +2 -0
  34. package/dist/cjs/store/reconcile.js +407 -255
  35. package/dist/cjs/store/reconcile.js.map +1 -1
  36. package/dist/cjs/store/sqlite/lexical.js +1 -1
  37. package/dist/cjs/store/sqlite/lexical.js.map +1 -1
  38. package/dist/cjs/store/sqlite/store.js +0 -1
  39. package/dist/cjs/store/sqlite/store.js.map +1 -1
  40. package/dist/cjs/store/stages.d.cts +18 -0
  41. package/dist/cjs/store/stages.d.ts +18 -0
  42. package/dist/cjs/store/stages.js +372 -0
  43. package/dist/cjs/store/stages.js.map +1 -0
  44. package/dist/cjs/store/turso/store.js.map +1 -1
  45. package/dist/cjs/store/types.d.cts +1 -1
  46. package/dist/cjs/store/types.d.ts +1 -1
  47. package/dist/cjs/store/types.js +0 -1
  48. package/dist/cjs/store/types.js.map +1 -1
  49. package/dist/cjs/text/segment.js +7 -5
  50. package/dist/cjs/text/segment.js.map +1 -1
  51. package/dist/cjs/watch.js +162 -107
  52. package/dist/cjs/watch.js.map +1 -1
  53. package/dist/cjs/workers/parse.d.cts +1 -0
  54. package/dist/cjs/workers/parse.d.ts +1 -0
  55. package/dist/cjs/workers/parse.js +4 -1
  56. package/dist/cjs/workers/parse.js.map +1 -1
  57. package/dist/esm/chunk/group.js +13 -9
  58. package/dist/esm/chunk/group.js.map +1 -1
  59. package/dist/esm/commands/search.js +1 -1
  60. package/dist/esm/commands/search.js.map +1 -1
  61. package/dist/esm/index.d.ts +1 -1
  62. package/dist/esm/index.js.map +1 -1
  63. package/dist/esm/scan/pool.d.ts +1 -0
  64. package/dist/esm/scan/pool.js +2 -1
  65. package/dist/esm/scan/pool.js.map +1 -1
  66. package/dist/esm/scan/reparse.d.ts +1 -0
  67. package/dist/esm/scan/reparse.js +5 -2
  68. package/dist/esm/scan/reparse.js.map +1 -1
  69. package/dist/esm/store/builder.d.ts +2 -0
  70. package/dist/esm/store/builder.js.map +1 -1
  71. package/dist/esm/store/index.d.ts +1 -5
  72. package/dist/esm/store/index.js +6 -28
  73. package/dist/esm/store/index.js.map +1 -1
  74. package/dist/esm/store/lock-wait.d.ts +2 -0
  75. package/dist/esm/store/lock-wait.js +36 -0
  76. package/dist/esm/store/lock-wait.js.map +1 -0
  77. package/dist/esm/store/open.d.ts +2 -4
  78. package/dist/esm/store/open.js +17 -32
  79. package/dist/esm/store/open.js.map +1 -1
  80. package/dist/esm/store/reconcile.d.ts +2 -0
  81. package/dist/esm/store/reconcile.js +72 -44
  82. package/dist/esm/store/reconcile.js.map +1 -1
  83. package/dist/esm/store/sqlite/lexical.js +1 -1
  84. package/dist/esm/store/sqlite/lexical.js.map +1 -1
  85. package/dist/esm/store/sqlite/store.js +0 -1
  86. package/dist/esm/store/sqlite/store.js.map +1 -1
  87. package/dist/esm/store/stages.d.ts +18 -0
  88. package/dist/esm/store/stages.js +63 -0
  89. package/dist/esm/store/stages.js.map +1 -0
  90. package/dist/esm/store/turso/store.js +1 -1
  91. package/dist/esm/store/turso/store.js.map +1 -1
  92. package/dist/esm/store/types.d.ts +1 -1
  93. package/dist/esm/store/types.js +0 -1
  94. package/dist/esm/store/types.js.map +1 -1
  95. package/dist/esm/text/segment.js +7 -5
  96. package/dist/esm/text/segment.js.map +1 -1
  97. package/dist/esm/watch.js +63 -38
  98. package/dist/esm/watch.js.map +1 -1
  99. package/dist/esm/workers/parse.d.ts +1 -0
  100. package/dist/esm/workers/parse.js +4 -1
  101. package/dist/esm/workers/parse.js.map +1 -1
  102. package/package.json +1 -1
  103. package/skills/sense/SKILL.md +1 -1
  104. package/skills/sense-setup/SKILL.md +1 -1
@@ -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>;
@@ -12,9 +12,6 @@ _export(exports, {
12
12
  get docCount () {
13
13
  return docCount;
14
14
  },
15
- get openWithBuilder () {
16
- return openWithBuilder;
17
- },
18
15
  get openWithDialect () {
19
16
  return openWithDialect;
20
17
  }
@@ -29,6 +26,7 @@ var _builderts = require("./builder.js");
29
26
  var _cachets = require("./cache.js");
30
27
  var _embedscopets = require("./embed-scope.js");
31
28
  var _featurescopets = require("./feature-scope.js");
29
+ var _lockwaitts = require("./lock-wait.js");
32
30
  var _presetscopets = require("./preset-scope.js");
33
31
  var _sharedts = require("./shared.js");
34
32
  var _signaturets = require("./signature.js");
@@ -157,19 +155,17 @@ function _ts_generator(thisArg, body) {
157
155
  };
158
156
  }
159
157
  }
160
- // duckdb and turso hold the cache file for their connection's whole life, not for a transaction,
161
- // so a second command waits on the first command finishing. Bounded rather than open-ended: this
162
- // clears a warm query's collision (~100ms) and still fails loudly behind a cold build instead of
163
- // looking hung.
164
- var LOCK_RETRY_MS = 5000;
158
+ // duckdb/turso hold the cache file for their connection's whole life, so a second command waits.
159
+ // Bounded by this tree's recorded reconcile time (lock-wait.ts), not a fixed guess.
165
160
  var LOCK_POLL_MS = 50;
166
161
  function connectUnlocked(dbPath, cfg, dialect) {
167
162
  return _async_to_generator(function() {
168
- var deadline, err, _dialect_isLocked;
163
+ var budgetMs, deadline, err, _dialect_isLocked;
169
164
  return _ts_generator(this, function(_state) {
170
165
  switch(_state.label){
171
166
  case 0:
172
- deadline = Date.now() + LOCK_RETRY_MS;
167
+ budgetMs = (0, _lockwaitts.lockWaitBudgetMs)(cfg.baseDir);
168
+ deadline = Date.now() + budgetMs;
173
169
  _state.label = 1;
174
170
  case 1:
175
171
  _state.trys.push([
@@ -191,7 +187,7 @@ function connectUnlocked(dbPath, cfg, dialect) {
191
187
  err = _state.sent();
192
188
  if (!((_dialect_isLocked = dialect.isLocked) === null || _dialect_isLocked === void 0 ? void 0 : _dialect_isLocked.call(dialect, err))) throw err;
193
189
  if (Date.now() >= deadline) {
194
- throw new _errorsts.SenseError('STORE_BUSY', "another sense process is using this tree's ".concat(cfg.store, " cache (").concat(dbPath, ") and did not release it within ").concat(LOCK_RETRY_MS / 1000, 's; wait for that command to finish, or set "store" to "sqlite" in sense.config.json, which serves concurrent commands'));
190
+ throw new _errorsts.SenseError('STORE_BUSY', "another sense process is using this tree's ".concat(cfg.store, " cache (").concat(dbPath, ") and did not release it within ").concat(Math.round(budgetMs / 1000), 's; wait for that command to finish, or set "store" to "sqlite" in sense.config.json, which serves concurrent commands'));
195
191
  }
196
192
  return [
197
193
  4,
@@ -218,9 +214,9 @@ function connectUnlocked(dbPath, cfg, dialect) {
218
214
  });
219
215
  })();
220
216
  }
221
- function connectWithDialect(cfg, dialect, keepBuilderOpen) {
217
+ function connectWithDialect(cfg, dialect) {
222
218
  return _async_to_generator(function() {
223
- var stateDir, dbPath, _ref, handle, conn, closed, builder, version, features, wantFeatures, forcedPaths, embedInvalidate, featureToggles, changedKeys, presetForced, embedKind, toggles, changed, changed1, changed2, _ref1, recordedMaxMs, embedParsed, _tmp, featureParsed, _tmp1, _ref2, parsed, warnings, err;
219
+ var stateDir, dbPath, _ref, handle, conn, closed, builder, version, features, wantFeatures, forcedPaths, embedInvalidate, featureToggles, changedKeys, presetForced, embedKind, toggles, changed, changed1, changed2, _ref1, recordedMaxMs, embedParsed, _tmp, featureParsed, _tmp1, _ref2, parsed, warnings, stages, err;
224
220
  return _ts_generator(this, function(_state) {
225
221
  switch(_state.label){
226
222
  case 0:
@@ -238,16 +234,16 @@ function connectWithDialect(cfg, dialect, keepBuilderOpen) {
238
234
  // A throw below must release this handle, or the leaked WAL makes the cache file undeletable on
239
235
  // Windows. `closed` keeps the catch from double-closing a handle a rebuild branch already closed.
240
236
  closed = false;
241
- // Created here, not inside reconcile(): its pool must survive across every build() call this
242
- // connection sees (a watcher's repeated ticks), not just the one below.
237
+ // Created here, not inside reconcile(): invalidate()/invalidateFeatures() below share its pool
238
+ // with the build() call that follows them.
243
239
  builder = (0, _builderts.createBuilder)(conn, cfg, cfg.baseDir, dialect.reconcileDialect);
244
240
  _state.label = 2;
245
241
  case 2:
246
242
  _state.trys.push([
247
243
  2,
248
- 31,
244
+ 30,
249
245
  ,
250
- 35
246
+ 34
251
247
  ]);
252
248
  return [
253
249
  4,
@@ -288,7 +284,7 @@ function connectWithDialect(cfg, dialect, keepBuilderOpen) {
288
284
  (0, _cachets.clearCache)(cfg);
289
285
  return [
290
286
  2,
291
- connectWithDialect(cfg, dialect, keepBuilderOpen)
287
+ connectWithDialect(cfg, dialect)
292
288
  ];
293
289
  case 7:
294
290
  changedKeys = (0, _signaturets.changedSignatureKeys)(features !== null && features !== void 0 ? features : '', wantFeatures);
@@ -396,7 +392,7 @@ function connectWithDialect(cfg, dialect, keepBuilderOpen) {
396
392
  (0, _cachets.clearCache)(cfg);
397
393
  return [
398
394
  2,
399
- connectWithDialect(cfg, dialect, keepBuilderOpen)
395
+ connectWithDialect(cfg, dialect)
400
396
  ];
401
397
  case 17:
402
398
  return [
@@ -468,19 +464,14 @@ function connectWithDialect(cfg, dialect, keepBuilderOpen) {
468
464
  builder.build(forcedPaths)
469
465
  ];
470
466
  case 28:
471
- _ref2 = _state.sent(), parsed = _ref2.parsed, warnings = _ref2.warnings;
472
- if (!!keepBuilderOpen) return [
473
- 3,
474
- 30
475
- ];
467
+ _ref2 = _state.sent(), parsed = _ref2.parsed, warnings = _ref2.warnings, stages = _ref2.stages;
468
+ // Every open reconciles once and is done with it -- a watcher opens fresh per event instead of holding this connection (src/watch.ts).
476
469
  return [
477
470
  4,
478
471
  builder.close()
479
472
  ];
480
473
  case 29:
481
474
  _state.sent();
482
- _state.label = 30;
483
- case 30:
484
475
  return [
485
476
  2,
486
477
  {
@@ -490,31 +481,31 @@ function connectWithDialect(cfg, dialect, keepBuilderOpen) {
490
481
  dbPath: dbPath,
491
482
  parsed: parsed + embedParsed + featureParsed,
492
483
  warnings: warnings,
493
- builder: builder
484
+ stages: stages
494
485
  }
495
486
  ];
496
- case 31:
487
+ case 30:
497
488
  err = _state.sent();
498
489
  return [
499
490
  4,
500
491
  builder.close()
501
492
  ];
502
- case 32:
493
+ case 31:
503
494
  _state.sent();
504
495
  if (!!closed) return [
505
496
  3,
506
- 34
497
+ 33
507
498
  ];
508
499
  return [
509
500
  4,
510
501
  dialect.close(handle)
511
502
  ];
512
- case 33:
503
+ case 32:
513
504
  _state.sent();
514
- _state.label = 34;
515
- case 34:
505
+ _state.label = 33;
506
+ case 33:
516
507
  throw err;
517
- case 35:
508
+ case 34:
518
509
  return [
519
510
  2
520
511
  ];
@@ -524,47 +515,19 @@ function connectWithDialect(cfg, dialect, keepBuilderOpen) {
524
515
  }
525
516
  function openWithDialect(cfg, dialect) {
526
517
  return _async_to_generator(function() {
527
- var _ref, handle, conn, resolvedCfg, dbPath, parsed, warnings, store;
518
+ var _ref, handle, conn, resolvedCfg, dbPath, parsed, warnings, stages, store;
528
519
  return _ts_generator(this, function(_state) {
529
520
  switch(_state.label){
530
521
  case 0:
531
522
  return [
532
523
  4,
533
- connectWithDialect(cfg, dialect, false)
524
+ connectWithDialect(cfg, dialect)
534
525
  ];
535
526
  case 1:
536
- _ref = _state.sent(), handle = _ref.handle, conn = _ref.conn, resolvedCfg = _ref.cfg, dbPath = _ref.dbPath, parsed = _ref.parsed, warnings = _ref.warnings;
527
+ _ref = _state.sent(), handle = _ref.handle, conn = _ref.conn, resolvedCfg = _ref.cfg, dbPath = _ref.dbPath, parsed = _ref.parsed, warnings = _ref.warnings, stages = _ref.stages;
537
528
  store = dialect.createStore(handle, conn, resolvedCfg);
538
529
  // reconcile ran before this object existed, so its chunk text is keyed by the connection.
539
530
  (0, _handoffts.rekeyChunkText)(conn, store);
540
- return [
541
- 2,
542
- {
543
- store: store,
544
- cfg: resolvedCfg,
545
- dbPath: dbPath,
546
- parsed: parsed,
547
- warnings: warnings
548
- }
549
- ];
550
- }
551
- });
552
- })();
553
- }
554
- function openWithBuilder(cfg, dialect) {
555
- return _async_to_generator(function() {
556
- var _ref, handle, conn, resolvedCfg, dbPath, parsed, warnings, builder, store;
557
- return _ts_generator(this, function(_state) {
558
- switch(_state.label){
559
- case 0:
560
- return [
561
- 4,
562
- connectWithDialect(cfg, dialect, true)
563
- ];
564
- case 1:
565
- _ref = _state.sent(), handle = _ref.handle, conn = _ref.conn, resolvedCfg = _ref.cfg, dbPath = _ref.dbPath, parsed = _ref.parsed, warnings = _ref.warnings, builder = _ref.builder;
566
- store = dialect.createStore(handle, conn, resolvedCfg);
567
- (0, _handoffts.rekeyChunkText)(conn, store);
568
531
  return [
569
532
  2,
570
533
  {
@@ -573,7 +536,7 @@ function openWithBuilder(cfg, dialect) {
573
536
  dbPath: dbPath,
574
537
  parsed: parsed,
575
538
  warnings: warnings,
576
- builder: builder
539
+ stages: stages
577
540
  }
578
541
  ];
579
542
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/open.ts"],"sourcesContent":["import { mkdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { ResolvedConfig } from '../config/index.ts';\nimport { featureSignature, STATE_DIR } from '../config/index.ts';\nimport { rekeyChunkText } from '../embed/handoff.ts';\nimport { SenseError } from '../errors.ts';\nimport { FEATURES } from '../features/index.ts';\nimport type { Builder } from './builder.ts';\nimport { createBuilder } from './builder.ts';\nimport { clearCache } from './cache.ts';\nimport type { EmbedChangeKind } from './embed-scope.ts';\nimport { classifyEmbedChange } from './embed-scope.ts';\nimport type { FeatureToggle } from './feature-scope.ts';\nimport { classifyFeatureToggles, isFeatureOnlyChange } from './feature-scope.ts';\nimport { forcedPresetPaths, isPresetOnlyChange } from './preset-scope.ts';\nimport { getMeta, setMeta } from './shared.ts';\nimport { changedSignatureKeys, embedIdentityAdopted, signatureDiff } from './signature.ts';\nimport type { Connection, OpenDialect, Store } from './types.ts';\n\n// One open algorithm shared by every store, parameterised by a per-engine OpenDialect (types.ts).\n// Ordering is universal, not a dialect concern: connect, meta table, schema-version and\n// feature-signature comparison (rebuild, adopt, or partial rebuild), any extra rebuild trigger,\n// ensureSchema, the derived busy_timeout PRAGMA, reconcile, then the store itself.\n\nexport interface OpenResult {\n store: Store;\n cfg: ResolvedConfig;\n dbPath: string;\n parsed: number;\n warnings: string[];\n}\n\ninterface ConnectResult<Handle> {\n handle: Handle;\n conn: Connection;\n cfg: ResolvedConfig;\n dbPath: string;\n parsed: number;\n warnings: string[];\n // Closed already unless `keepBuilderOpen` was set: a one-shot open reconciles once and is done\n // with it, a watcher keeps calling build() on the same instance across its whole run.\n builder: Builder;\n}\n\n// duckdb and turso hold the cache file for their connection's whole life, not for a transaction,\n// so a second command waits on the first command finishing. Bounded rather than open-ended: this\n// clears a warm query's collision (~100ms) and still fails loudly behind a cold build instead of\n// looking hung.\nconst LOCK_RETRY_MS = 5_000;\nconst LOCK_POLL_MS = 50;\n\nasync function connectUnlocked<Handle>(dbPath: string, cfg: ResolvedConfig, dialect: OpenDialect<Handle>): Promise<{ handle: Handle; conn: Connection }> {\n const deadline = Date.now() + LOCK_RETRY_MS;\n for (;;) {\n try {\n return await dialect.connect(dbPath, cfg);\n } catch (err) {\n if (!dialect.isLocked?.(err as Error)) throw err;\n if (Date.now() >= deadline) {\n throw new SenseError('STORE_BUSY', `another sense process is using this tree's ${cfg.store} cache (${dbPath}) and did not release it within ${LOCK_RETRY_MS / 1000}s; wait for that command to finish, or set \"store\" to \"sqlite\" in sense.config.json, which serves concurrent commands`);\n }\n await new Promise((resolve) => setTimeout(resolve, LOCK_POLL_MS));\n }\n }\n}\n\nasync function connectWithDialect<Handle>(cfg: ResolvedConfig, dialect: OpenDialect<Handle>, keepBuilderOpen: boolean): Promise<ConnectResult<Handle>> {\n const stateDir = join(cfg.baseDir, STATE_DIR);\n mkdirSync(stateDir, { recursive: true });\n const dbPath = join(stateDir, dialect.filename);\n\n const { handle, conn } = await connectUnlocked(dbPath, cfg, dialect);\n // A throw below must release this handle, or the leaked WAL makes the cache file undeletable on\n // Windows. `closed` keeps the catch from double-closing a handle a rebuild branch already closed.\n let closed = false;\n // Created here, not inside reconcile(): its pool must survive across every build() call this\n // connection sees (a watcher's repeated ticks), not just the one below.\n const builder = createBuilder(conn, cfg, cfg.baseDir, dialect.reconcileDialect);\n try {\n await conn.exec('CREATE TABLE IF NOT EXISTS meta (key TEXT PRIMARY KEY, value TEXT)');\n\n // Schema-version or feature-set mismatch: reconcile only reparses changed files, so an\n // old cache can't be patched incrementally -- rebuild instead (cheap: nothing expensive lives here).\n const version = await getMeta(conn, 'schema_version');\n const features = await getMeta(conn, 'features');\n const wantFeatures = featureSignature(cfg, FEATURES);\n // Set only by the preset-membership branch below; reconcile treats these paths as touched\n // despite an unchanged stamp, for this one build() call.\n let forcedPaths: Set<string> | undefined;\n // Set only by the embed-narrow branch below; applied via builder.invalidate() after ensureSchema.\n let embedInvalidate: EmbedChangeKind | undefined;\n // Set only by the feature-toggle branch below; applied via builder.invalidateFeatures() after ensureSchema.\n let featureToggles: FeatureToggle[] | undefined;\n if ((version !== null && version !== dialect.schemaVersion) || (features !== null && features !== wantFeatures)) {\n // Indexing derives from presets, so a config edit rebuilding the cache must say so and\n // name what changed -- silent rebuilds make derived indexing look like a hang or a bug.\n if (version !== null && version !== dialect.schemaVersion) {\n console.error('sense: cache format changed (new sensemaking version); rebuilding the index');\n // Close before clearCache deletes the files out from under the still-open handle.\n closed = true;\n await dialect.close(handle);\n clearCache(cfg);\n return connectWithDialect(cfg, dialect, keepBuilderOpen);\n }\n const changedKeys = changedSignatureKeys(features ?? '', wantFeatures);\n // Null (rather than the empty set) when changedKeys isn't preset-only, or a changed\n // preset's stored segment can't be parsed back into old include/exclude/vectors -- either\n // way the branch below is skipped and the full rebuild stays the fallback.\n const presetForced = isPresetOnlyChange(changedKeys) ? forcedPresetPaths(cfg, cfg.baseDir, features ?? '', changedKeys) : null;\n // Null unless exactly one segment changed and it decomposes into a recognised embed-only\n // case (embed-scope.ts): anything else, including embed toggled on/off, stays null.\n const embedKind = changedKeys.size === 1 && changedKeys.has('embed') ? classifyEmbedChange(features ?? '', wantFeatures) : null;\n // Null (rather than the empty set) when changedKeys isn't feature-toggle-only, or a changed\n // feature's stored segment can't be parsed back into old/new on-off -- either way the branch\n // below is skipped and the full rebuild stays the fallback.\n const toggles = isFeatureOnlyChange(changedKeys) ? classifyFeatureToggles(features ?? '', wantFeatures, changedKeys) : null;\n if (changedKeys.size === 1 && changedKeys.has('embed') && embedIdentityAdopted(features ?? '', wantFeatures)) {\n // First sight of a resolved weight identity: the model itself hasn't changed, so\n // adopt it into meta with no rebuild and no re-embed.\n console.error(\"sense: recorded the embedding model's resolved identity; vectors are unaffected\");\n await setMeta(conn, 'features', wantFeatures);\n } else if (embedKind !== null) {\n // Chunk boundaries are file-derived, not model-derived (embed.ts's chunksOf), so neither\n // case needs any file reparsed for any feature but embed itself.\n embedInvalidate = embedKind;\n console.error(embedKind === 'model' ? 'sense: config change (embed settings) invalidates only the stale vectors' : 'sense: config change (embed settings) rebuilds only the embeddings it affects');\n await setMeta(conn, 'features', wantFeatures);\n } else if (presetForced !== null) {\n // Membership only: which files a preset covers moved, not a file's own content, a\n // global feature, or the embed model. reconcile() already knows how to\n // add, update, and remove a file correctly (every cross-feature cascade included); it\n // just needs telling which unchanged files to treat as touched (forcedPaths, above).\n forcedPaths = presetForced;\n const changed = signatureDiff(features ?? '', wantFeatures);\n console.error(`sense: config change (${changed}) reparses only the files it affects`);\n await setMeta(conn, 'features', wantFeatures);\n } else if (toggles !== null) {\n // A feature turned off or on: reconcile.ts's activeFeatures skips a disabled feature's\n // hooks entirely, so its rows rot while off -- invalidateFeatures drops them and, for a\n // feature turning back on, fully re-derives across every indexed file rather than\n // trusting rows written before or during that window.\n featureToggles = toggles;\n const changed = signatureDiff(features ?? '', wantFeatures);\n console.error(`sense: config change (${changed}) reparses only the feature it affects`);\n await setMeta(conn, 'features', wantFeatures);\n } else {\n const changed = signatureDiff(features ?? '', wantFeatures);\n console.error(`sense: config change (${changed}) rebuilds the index`);\n closed = true;\n await dialect.close(handle);\n clearCache(cfg);\n return connectWithDialect(cfg, dialect, keepBuilderOpen);\n }\n }\n\n await dialect.ensureSchema(handle, conn, cfg);\n\n // 3x the largest reconcile this cache has recorded, floored at 30s and capped at 10min.\n // Installed before build() -- that call is the one that races a watcher's transaction.\n if (dialect.setDerivedBusyTimeout) {\n const recordedMaxMs = Number((await getMeta(conn, 'reconcile_max_ms')) ?? '0');\n await dialect.setDerivedBusyTimeout(handle, conn, Math.min(Math.max(30000, 3 * recordedMaxMs), 600_000));\n }\n\n // Runs before build(): forcedPaths, embedInvalidate and featureToggles never target the same\n // call (each comes from its own mutually exclusive branch above: a preset-only, embed-only, or\n // feature-toggle-only changed-key set).\n const embedParsed = embedInvalidate ? (await builder.invalidate(embedInvalidate)).parsed : 0;\n const featureParsed = featureToggles ? (await builder.invalidateFeatures(featureToggles)).parsed : 0;\n\n const { parsed, warnings } = await builder.build(forcedPaths);\n // A one-shot open is done reconciling for good; a watcher keeps `builder` alive across its run.\n if (!keepBuilderOpen) await builder.close();\n\n return { handle, conn, cfg, dbPath, parsed: parsed + embedParsed + featureParsed, warnings, builder };\n } catch (err) {\n await builder.close();\n if (!closed) await dialect.close(handle);\n throw err;\n }\n}\n\n// A store's open(): connects (see connectWithDialect above), then wraps the resulting connection\n// in the Store interface. The builder's pool closes right after the initial build.\nexport async function openWithDialect<Handle>(cfg: ResolvedConfig, dialect: OpenDialect<Handle>): Promise<OpenResult> {\n const { handle, conn, cfg: resolvedCfg, dbPath, parsed, warnings } = await connectWithDialect(cfg, dialect, false);\n const store = dialect.createStore(handle, conn, resolvedCfg);\n // reconcile ran before this object existed, so its chunk text is keyed by the connection.\n rekeyChunkText(conn, store);\n return { store, cfg: resolvedCfg, dbPath, parsed, warnings };\n}\n\n// Same connect+build as openWithDialect, but keeps the builder's pool alive and hands it back\n// alongside the store, for a caller (a watcher) that reconciles repeatedly on this connection.\nexport async function openWithBuilder<Handle>(cfg: ResolvedConfig, dialect: OpenDialect<Handle>): Promise<OpenResult & { builder: Builder }> {\n const { handle, conn, cfg: resolvedCfg, dbPath, parsed, warnings, builder } = await connectWithDialect(cfg, dialect, true);\n const store = dialect.createStore(handle, conn, resolvedCfg);\n rekeyChunkText(conn, store);\n return { store, cfg: resolvedCfg, dbPath, parsed, warnings, builder };\n}\n\nexport async function docCount(store: Store): Promise<number> {\n const stmt = await store.prepare('SELECT COUNT(*) AS n FROM frontmatter');\n return ((await stmt.get()) as { n: number }).n;\n}\n"],"names":["docCount","openWithBuilder","openWithDialect","LOCK_RETRY_MS","LOCK_POLL_MS","connectUnlocked","dbPath","cfg","dialect","deadline","err","Date","now","connect","isLocked","SenseError","store","Promise","resolve","setTimeout","connectWithDialect","keepBuilderOpen","stateDir","handle","conn","closed","builder","version","features","wantFeatures","forcedPaths","embedInvalidate","featureToggles","changedKeys","presetForced","embedKind","toggles","changed","recordedMaxMs","embedParsed","featureParsed","parsed","warnings","join","baseDir","STATE_DIR","mkdirSync","recursive","filename","createBuilder","reconcileDialect","exec","getMeta","featureSignature","FEATURES","schemaVersion","console","error","close","clearCache","changedSignatureKeys","isPresetOnlyChange","forcedPresetPaths","size","has","classifyEmbedChange","isFeatureOnlyChange","classifyFeatureToggles","embedIdentityAdopted","setMeta","signatureDiff","ensureSchema","setDerivedBusyTimeout","Number","Math","min","max","invalidate","invalidateFeatures","build","resolvedCfg","createStore","rekeyChunkText","stmt","prepare","get","n"],"mappings":";;;;;;;;;;;QAyMsBA;eAAAA;;QAPAC;eAAAA;;QAVAC;eAAAA;;;sBAxLI;wBACL;uBAEuB;yBACb;wBACJ;wBACF;yBAEK;uBACH;4BAES;8BAEwB;6BACN;wBACrB;2BACyC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4B1E,iGAAiG;AACjG,iGAAiG;AACjG,iGAAiG;AACjG,gBAAgB;AAChB,IAAMC,gBAAgB;AACtB,IAAMC,eAAe;AAErB,SAAeC,gBAAwBC,MAAc,EAAEC,GAAmB,EAAEC,OAA4B;;YAChGC,UAIKC,KACFF;;;;oBALHC,WAAWE,KAAKC,GAAG,KAAKT;;;;;;;;;oBAGnB;;wBAAMK,QAAQK,OAAO,CAACP,QAAQC;;;oBAArC;;wBAAO;;;oBACAG;oBACP,IAAI,GAACF,oBAAAA,QAAQM,QAAQ,cAAhBN,wCAAAA,uBAAAA,SAAmBE,OAAe,MAAMA;oBAC7C,IAAIC,KAAKC,GAAG,MAAMH,UAAU;wBAC1B,MAAM,IAAIM,oBAAU,CAAC,cAAc,AAAC,8CAAiET,OAApBC,IAAIS,KAAK,EAAC,YAAmDb,OAAzCG,QAAO,oCAAuD,OAArBH,gBAAgB,MAAK;oBACrK;oBACA;;wBAAM,IAAIc,QAAQ,SAACC;mCAAYC,WAAWD,SAASd;;;;oBAAnD;;;;;;;;;;;;;;;;IAGN;;AAEA,SAAegB,mBAA2Bb,GAAmB,EAAEC,OAA4B,EAAEa,eAAwB;;YAC7GC,UAEAhB,QAEmB,MAAjBiB,QAAQC,MAGZC,QAGEC,SAMEC,SACAC,UACAC,cAGFC,aAEAC,iBAEAC,gBAYIC,aAIAC,cAGAC,WAIAC,SAkBEC,SASAA,UAIAA,UAcsB,OAAxBC,eAOFC,mBACAC,sBAEuB,OAArBC,QAAQC,UAKThC;;;;oBA5GHY,WAAWqB,IAAAA,cAAI,EAACpC,IAAIqC,OAAO,EAAEC,kBAAS;oBAC5CC,IAAAA,iBAAS,EAACxB,UAAU;wBAAEyB,WAAW;oBAAK;oBAChCzC,SAASqC,IAAAA,cAAI,EAACrB,UAAUd,QAAQwC,QAAQ;oBAErB;;wBAAM3C,gBAAgBC,QAAQC,KAAKC;;;oBAAnC,OAAA,eAAjBe,SAAiB,KAAjBA,QAAQC,OAAS,KAATA;oBAChB,gGAAgG;oBAChG,kGAAkG;oBAC9FC,SAAS;oBACb,6FAA6F;oBAC7F,wEAAwE;oBAClEC,UAAUuB,IAAAA,wBAAa,EAACzB,MAAMjB,KAAKA,IAAIqC,OAAO,EAAEpC,QAAQ0C,gBAAgB;;;;;;;;;oBAE5E;;wBAAM1B,KAAK2B,IAAI,CAAC;;;oBAAhB;oBAIgB;;wBAAMC,IAAAA,iBAAO,EAAC5B,MAAM;;;oBAA9BG,UAAU;oBACC;;wBAAMyB,IAAAA,iBAAO,EAAC5B,MAAM;;;oBAA/BI,WAAW;oBACXC,eAAewB,IAAAA,yBAAgB,EAAC9C,KAAK+C,kBAAQ;yBAQ/C,CAAA,AAAC3B,YAAY,QAAQA,YAAYnB,QAAQ+C,aAAa,IAAM3B,aAAa,QAAQA,aAAaC,YAAY,GAA1G;;;;yBAGEF,CAAAA,YAAY,QAAQA,YAAYnB,QAAQ+C,aAAa,AAAD,GAApD5B;;;;oBACF6B,QAAQC,KAAK,CAAC;oBACd,kFAAkF;oBAClFhC,SAAS;oBACT;;wBAAMjB,QAAQkD,KAAK,CAACnC;;;oBAApB;oBACAoC,IAAAA,mBAAU,EAACpD;oBACX;;wBAAOa,mBAAmBb,KAAKC,SAASa;;;oBAEpCY,cAAc2B,IAAAA,iCAAoB,EAAChC,qBAAAA,sBAAAA,WAAY,IAAIC;oBACzD,oFAAoF;oBACpF,0FAA0F;oBAC1F,2EAA2E;oBACrEK,eAAe2B,IAAAA,iCAAkB,EAAC5B,eAAe6B,IAAAA,gCAAiB,EAACvD,KAAKA,IAAIqC,OAAO,EAAEhB,qBAAAA,sBAAAA,WAAY,IAAIK,eAAe;oBAC1H,yFAAyF;oBACzF,oFAAoF;oBAC9EE,YAAYF,YAAY8B,IAAI,KAAK,KAAK9B,YAAY+B,GAAG,CAAC,WAAWC,IAAAA,iCAAmB,EAACrC,qBAAAA,sBAAAA,WAAY,IAAIC,gBAAgB;oBAC3H,4FAA4F;oBAC5F,6FAA6F;oBAC7F,4DAA4D;oBACtDO,UAAU8B,IAAAA,mCAAmB,EAACjC,eAAekC,IAAAA,sCAAsB,EAACvC,qBAAAA,sBAAAA,WAAY,IAAIC,cAAcI,eAAe;yBACnHA,CAAAA,YAAY8B,IAAI,KAAK,KAAK9B,YAAY+B,GAAG,CAAC,YAAYI,IAAAA,iCAAoB,EAACxC,qBAAAA,sBAAAA,WAAY,IAAIC,aAAY,GAAvGI;;;;oBACF,iFAAiF;oBACjF,sDAAsD;oBACtDuB,QAAQC,KAAK,CAAC;oBACd;;wBAAMY,IAAAA,iBAAO,EAAC7C,MAAM,YAAYK;;;oBAAhC;;;;;;yBACSM,CAAAA,cAAc,IAAG,GAAjBA;;;;oBACT,yFAAyF;oBACzF,iEAAiE;oBACjEJ,kBAAkBI;oBAClBqB,QAAQC,KAAK,CAACtB,cAAc,UAAU,6EAA6E;oBACnH;;wBAAMkC,IAAAA,iBAAO,EAAC7C,MAAM,YAAYK;;;oBAAhC;;;;;;yBACSK,CAAAA,iBAAiB,IAAG,GAApBA;;;;oBACT,kFAAkF;oBAClF,uEAAuE;oBACvE,sFAAsF;oBACtF,qFAAqF;oBACrFJ,cAAcI;oBACRG,UAAUiC,IAAAA,0BAAa,EAAC1C,qBAAAA,sBAAAA,WAAY,IAAIC;oBAC9C2B,QAAQC,KAAK,CAAC,AAAC,yBAAgC,OAARpB,SAAQ;oBAC/C;;wBAAMgC,IAAAA,iBAAO,EAAC7C,MAAM,YAAYK;;;oBAAhC;;;;;;yBACSO,CAAAA,YAAY,IAAG,GAAfA;;;;oBACT,uFAAuF;oBACvF,wFAAwF;oBACxF,kFAAkF;oBAClF,sDAAsD;oBACtDJ,iBAAiBI;oBACXC,WAAUiC,IAAAA,0BAAa,EAAC1C,qBAAAA,sBAAAA,WAAY,IAAIC;oBAC9C2B,QAAQC,KAAK,CAAC,AAAC,yBAAgC,OAARpB,UAAQ;oBAC/C;;wBAAMgC,IAAAA,iBAAO,EAAC7C,MAAM,YAAYK;;;oBAAhC;;;;;;oBAEMQ,WAAUiC,IAAAA,0BAAa,EAAC1C,qBAAAA,sBAAAA,WAAY,IAAIC;oBAC9C2B,QAAQC,KAAK,CAAC,AAAC,yBAAgC,OAARpB,UAAQ;oBAC/CZ,SAAS;oBACT;;wBAAMjB,QAAQkD,KAAK,CAACnC;;;oBAApB;oBACAoC,IAAAA,mBAAU,EAACpD;oBACX;;wBAAOa,mBAAmBb,KAAKC,SAASa;;;oBAI5C;;wBAAMb,QAAQ+D,YAAY,CAAChD,QAAQC,MAAMjB;;;oBAAzC;yBAIIC,QAAQgE,qBAAqB,EAA7BhE;;;;oBAC4B;;wBAAM4C,IAAAA,iBAAO,EAAC5B,MAAM;;;oBAA5Cc,gBAAgBmC;yBAAQ,QAAA,2BAAA,mBAAA,QAA4C;;oBAC1E;;wBAAMjE,QAAQgE,qBAAqB,CAACjD,QAAQC,MAAMkD,KAAKC,GAAG,CAACD,KAAKE,GAAG,CAAC,OAAO,IAAItC,gBAAgB;;;oBAA/F;;;yBAMkBP,iBAAAA;;;;oBAAmB;;wBAAML,QAAQmD,UAAU,CAAC9C;;;2BAA1B,AAAC,cAA2CU,MAAM;;;;;;2BAAG;;;oBAArFF;yBACgBP,gBAAAA;;;;oBAAkB;;wBAAMN,QAAQoD,kBAAkB,CAAC9C;;;4BAAlC,AAAC,cAAkDS,MAAM;;;;;;4BAAG;;;oBAA7FD;oBAEuB;;wBAAMd,QAAQqD,KAAK,CAACjD;;;oBAApB,QAAA,eAArBW,SAAqB,MAArBA,QAAQC,WAAa,MAAbA;yBAEZ,CAACrB,iBAAD;;;;oBAAkB;;wBAAMK,QAAQgC,KAAK;;;oBAAnB;;;oBAEtB;;wBAAO;4BAAEnC,QAAAA;4BAAQC,MAAAA;4BAAMjB,KAAAA;4BAAKD,QAAAA;4BAAQmC,QAAQA,SAASF,cAAcC;4BAAeE,UAAAA;4BAAUhB,SAAAA;wBAAQ;;;oBAC7FhB;oBACP;;wBAAMgB,QAAQgC,KAAK;;;oBAAnB;yBACI,CAACjC,QAAD;;;;oBAAS;;wBAAMjB,QAAQkD,KAAK,CAACnC;;;oBAApB;;;oBACb,MAAMb;;;;;;;IAEV;;AAIO,SAAeR,gBAAwBK,GAAmB,EAAEC,OAA4B;;YACxB,MAA7De,QAAQC,MAAWwD,aAAa1E,QAAQmC,QAAQC,UAClD1B;;;;oBAD+D;;wBAAMI,mBAAmBb,KAAKC,SAAS;;;oBAAvC,OAAA,eAA7De,SAA6D,KAA7DA,QAAQC,OAAqD,KAArDA,MAAWwD,cAA0C,KAA/CzE,KAAkBD,SAA6B,KAA7BA,QAAQmC,SAAqB,KAArBA,QAAQC,WAAa,KAAbA;oBAClD1B,QAAQR,QAAQyE,WAAW,CAAC1D,QAAQC,MAAMwD;oBAChD,0FAA0F;oBAC1FE,IAAAA,yBAAc,EAAC1D,MAAMR;oBACrB;;wBAAO;4BAAEA,OAAAA;4BAAOT,KAAKyE;4BAAa1E,QAAAA;4BAAQmC,QAAAA;4BAAQC,UAAAA;wBAAS;;;;IAC7D;;AAIO,SAAezC,gBAAwBM,GAAmB,EAAEC,OAA4B;;YACf,MAAtEe,QAAQC,MAAWwD,aAAa1E,QAAQmC,QAAQC,UAAUhB,SAC5DV;;;;oBADwE;;wBAAMI,mBAAmBb,KAAKC,SAAS;;;oBAAvC,OAAA,eAAtEe,SAAsE,KAAtEA,QAAQC,OAA8D,KAA9DA,MAAWwD,cAAmD,KAAxDzE,KAAkBD,SAAsC,KAAtCA,QAAQmC,SAA8B,KAA9BA,QAAQC,WAAsB,KAAtBA,UAAUhB,UAAY,KAAZA;oBAC5DV,QAAQR,QAAQyE,WAAW,CAAC1D,QAAQC,MAAMwD;oBAChDE,IAAAA,yBAAc,EAAC1D,MAAMR;oBACrB;;wBAAO;4BAAEA,OAAAA;4BAAOT,KAAKyE;4BAAa1E,QAAAA;4BAAQmC,QAAAA;4BAAQC,UAAAA;4BAAUhB,SAAAA;wBAAQ;;;;IACtE;;AAEO,SAAe1B,SAASgB,KAAY;;YACnCmE;;;;oBAAO;;wBAAMnE,MAAMoE,OAAO,CAAC;;;oBAA3BD,OAAO;oBACJ;;wBAAMA,KAAKE,GAAG;;;oBAAvB;;wBAAS,cAAoCC,CAAC;;;;IAChD"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/open.ts"],"sourcesContent":["import { mkdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { ResolvedConfig } from '../config/index.ts';\nimport { featureSignature, STATE_DIR } from '../config/index.ts';\nimport { rekeyChunkText } from '../embed/handoff.ts';\nimport { SenseError } from '../errors.ts';\nimport { FEATURES } from '../features/index.ts';\nimport { createBuilder } from './builder.ts';\nimport { clearCache } from './cache.ts';\nimport type { EmbedChangeKind } from './embed-scope.ts';\nimport { classifyEmbedChange } from './embed-scope.ts';\nimport type { FeatureToggle } from './feature-scope.ts';\nimport { classifyFeatureToggles, isFeatureOnlyChange } from './feature-scope.ts';\nimport { lockWaitBudgetMs } from './lock-wait.ts';\nimport { forcedPresetPaths, isPresetOnlyChange } from './preset-scope.ts';\nimport { getMeta, setMeta } from './shared.ts';\nimport { changedSignatureKeys, embedIdentityAdopted, signatureDiff } from './signature.ts';\nimport type { Stages } from './stages.ts';\nimport type { Connection, OpenDialect, Store } from './types.ts';\n\n// One open algorithm shared by every store, parameterised by a per-engine OpenDialect (types.ts).\n// Ordering is universal, not a dialect concern: connect, meta table, schema-version and\n// feature-signature comparison (rebuild, adopt, or partial rebuild), any extra rebuild trigger,\n// ensureSchema, the derived busy_timeout PRAGMA, reconcile, then the store itself.\n\nexport interface OpenResult {\n store: Store;\n cfg: ResolvedConfig;\n dbPath: string;\n parsed: number;\n warnings: string[];\n // Per-stage wall time for this open's build pass (stages.ts), not for any narrow embed or\n // feature invalidation that ran beside it -- on a cold build there is none, so it is the whole cost.\n stages: Stages;\n}\n\ninterface ConnectResult<Handle> {\n handle: Handle;\n conn: Connection;\n cfg: ResolvedConfig;\n dbPath: string;\n parsed: number;\n warnings: string[];\n stages: Stages;\n}\n\n// duckdb/turso hold the cache file for their connection's whole life, so a second command waits.\n// Bounded by this tree's recorded reconcile time (lock-wait.ts), not a fixed guess.\nconst LOCK_POLL_MS = 50;\n\nasync function connectUnlocked<Handle>(dbPath: string, cfg: ResolvedConfig, dialect: OpenDialect<Handle>): Promise<{ handle: Handle; conn: Connection }> {\n const budgetMs = lockWaitBudgetMs(cfg.baseDir);\n const deadline = Date.now() + budgetMs;\n for (;;) {\n try {\n return await dialect.connect(dbPath, cfg);\n } catch (err) {\n if (!dialect.isLocked?.(err as Error)) throw err;\n if (Date.now() >= deadline) {\n throw new SenseError('STORE_BUSY', `another sense process is using this tree's ${cfg.store} cache (${dbPath}) and did not release it within ${Math.round(budgetMs / 1000)}s; wait for that command to finish, or set \"store\" to \"sqlite\" in sense.config.json, which serves concurrent commands`);\n }\n await new Promise((resolve) => setTimeout(resolve, LOCK_POLL_MS));\n }\n }\n}\n\nasync function connectWithDialect<Handle>(cfg: ResolvedConfig, dialect: OpenDialect<Handle>): Promise<ConnectResult<Handle>> {\n const stateDir = join(cfg.baseDir, STATE_DIR);\n mkdirSync(stateDir, { recursive: true });\n const dbPath = join(stateDir, dialect.filename);\n\n const { handle, conn } = await connectUnlocked(dbPath, cfg, dialect);\n // A throw below must release this handle, or the leaked WAL makes the cache file undeletable on\n // Windows. `closed` keeps the catch from double-closing a handle a rebuild branch already closed.\n let closed = false;\n // Created here, not inside reconcile(): invalidate()/invalidateFeatures() below share its pool\n // with the build() call that follows them.\n const builder = createBuilder(conn, cfg, cfg.baseDir, dialect.reconcileDialect);\n try {\n await conn.exec('CREATE TABLE IF NOT EXISTS meta (key TEXT PRIMARY KEY, value TEXT)');\n\n // Schema-version or feature-set mismatch: reconcile only reparses changed files, so an\n // old cache can't be patched incrementally -- rebuild instead (cheap: nothing expensive lives here).\n const version = await getMeta(conn, 'schema_version');\n const features = await getMeta(conn, 'features');\n const wantFeatures = featureSignature(cfg, FEATURES);\n // Set only by the preset-membership branch below; reconcile treats these paths as touched\n // despite an unchanged stamp, for this one build() call.\n let forcedPaths: Set<string> | undefined;\n // Set only by the embed-narrow branch below; applied via builder.invalidate() after ensureSchema.\n let embedInvalidate: EmbedChangeKind | undefined;\n // Set only by the feature-toggle branch below; applied via builder.invalidateFeatures() after ensureSchema.\n let featureToggles: FeatureToggle[] | undefined;\n if ((version !== null && version !== dialect.schemaVersion) || (features !== null && features !== wantFeatures)) {\n // Indexing derives from presets, so a config edit rebuilding the cache must say so and\n // name what changed -- silent rebuilds make derived indexing look like a hang or a bug.\n if (version !== null && version !== dialect.schemaVersion) {\n console.error('sense: cache format changed (new sensemaking version); rebuilding the index');\n // Close before clearCache deletes the files out from under the still-open handle.\n closed = true;\n await dialect.close(handle);\n clearCache(cfg);\n return connectWithDialect(cfg, dialect);\n }\n const changedKeys = changedSignatureKeys(features ?? '', wantFeatures);\n // Null (rather than the empty set) when changedKeys isn't preset-only, or a changed\n // preset's stored segment can't be parsed back into old include/exclude/vectors -- either\n // way the branch below is skipped and the full rebuild stays the fallback.\n const presetForced = isPresetOnlyChange(changedKeys) ? forcedPresetPaths(cfg, cfg.baseDir, features ?? '', changedKeys) : null;\n // Null unless exactly one segment changed and it decomposes into a recognised embed-only\n // case (embed-scope.ts): anything else, including embed toggled on/off, stays null.\n const embedKind = changedKeys.size === 1 && changedKeys.has('embed') ? classifyEmbedChange(features ?? '', wantFeatures) : null;\n // Null (rather than the empty set) when changedKeys isn't feature-toggle-only, or a changed\n // feature's stored segment can't be parsed back into old/new on-off -- either way the branch\n // below is skipped and the full rebuild stays the fallback.\n const toggles = isFeatureOnlyChange(changedKeys) ? classifyFeatureToggles(features ?? '', wantFeatures, changedKeys) : null;\n if (changedKeys.size === 1 && changedKeys.has('embed') && embedIdentityAdopted(features ?? '', wantFeatures)) {\n // First sight of a resolved weight identity: the model itself hasn't changed, so\n // adopt it into meta with no rebuild and no re-embed.\n console.error(\"sense: recorded the embedding model's resolved identity; vectors are unaffected\");\n await setMeta(conn, 'features', wantFeatures);\n } else if (embedKind !== null) {\n // Chunk boundaries are file-derived, not model-derived (embed.ts's chunksOf), so neither\n // case needs any file reparsed for any feature but embed itself.\n embedInvalidate = embedKind;\n console.error(embedKind === 'model' ? 'sense: config change (embed settings) invalidates only the stale vectors' : 'sense: config change (embed settings) rebuilds only the embeddings it affects');\n await setMeta(conn, 'features', wantFeatures);\n } else if (presetForced !== null) {\n // Membership only: which files a preset covers moved, not a file's own content, a\n // global feature, or the embed model. reconcile() already knows how to\n // add, update, and remove a file correctly (every cross-feature cascade included); it\n // just needs telling which unchanged files to treat as touched (forcedPaths, above).\n forcedPaths = presetForced;\n const changed = signatureDiff(features ?? '', wantFeatures);\n console.error(`sense: config change (${changed}) reparses only the files it affects`);\n await setMeta(conn, 'features', wantFeatures);\n } else if (toggles !== null) {\n // A feature turned off or on: reconcile.ts's activeFeatures skips a disabled feature's\n // hooks entirely, so its rows rot while off -- invalidateFeatures drops them and, for a\n // feature turning back on, fully re-derives across every indexed file rather than\n // trusting rows written before or during that window.\n featureToggles = toggles;\n const changed = signatureDiff(features ?? '', wantFeatures);\n console.error(`sense: config change (${changed}) reparses only the feature it affects`);\n await setMeta(conn, 'features', wantFeatures);\n } else {\n const changed = signatureDiff(features ?? '', wantFeatures);\n console.error(`sense: config change (${changed}) rebuilds the index`);\n closed = true;\n await dialect.close(handle);\n clearCache(cfg);\n return connectWithDialect(cfg, dialect);\n }\n }\n\n await dialect.ensureSchema(handle, conn, cfg);\n\n // 3x the largest reconcile this cache has recorded, floored at 30s and capped at 10min.\n // Installed before build() -- that call is the one that races a watcher's transaction.\n if (dialect.setDerivedBusyTimeout) {\n const recordedMaxMs = Number((await getMeta(conn, 'reconcile_max_ms')) ?? '0');\n await dialect.setDerivedBusyTimeout(handle, conn, Math.min(Math.max(30000, 3 * recordedMaxMs), 600_000));\n }\n\n // Runs before build(): forcedPaths, embedInvalidate and featureToggles never target the same\n // call (each comes from its own mutually exclusive branch above: a preset-only, embed-only, or\n // feature-toggle-only changed-key set).\n const embedParsed = embedInvalidate ? (await builder.invalidate(embedInvalidate)).parsed : 0;\n const featureParsed = featureToggles ? (await builder.invalidateFeatures(featureToggles)).parsed : 0;\n\n const { parsed, warnings, stages } = await builder.build(forcedPaths);\n // Every open reconciles once and is done with it -- a watcher opens fresh per event instead of holding this connection (src/watch.ts).\n await builder.close();\n\n return { handle, conn, cfg, dbPath, parsed: parsed + embedParsed + featureParsed, warnings, stages };\n } catch (err) {\n await builder.close();\n if (!closed) await dialect.close(handle);\n throw err;\n }\n}\n\n// A store's open(): connects (see connectWithDialect above), then wraps the resulting connection\n// in the Store interface. The builder's pool closes right after the initial build.\nexport async function openWithDialect<Handle>(cfg: ResolvedConfig, dialect: OpenDialect<Handle>): Promise<OpenResult> {\n const { handle, conn, cfg: resolvedCfg, dbPath, parsed, warnings, stages } = await connectWithDialect(cfg, dialect);\n const store = dialect.createStore(handle, conn, resolvedCfg);\n // reconcile ran before this object existed, so its chunk text is keyed by the connection.\n rekeyChunkText(conn, store);\n return { store, cfg: resolvedCfg, dbPath, parsed, warnings, stages };\n}\n\nexport async function docCount(store: Store): Promise<number> {\n const stmt = await store.prepare('SELECT COUNT(*) AS n FROM frontmatter');\n return ((await stmt.get()) as { n: number }).n;\n}\n"],"names":["docCount","openWithDialect","LOCK_POLL_MS","connectUnlocked","dbPath","cfg","dialect","budgetMs","deadline","err","lockWaitBudgetMs","baseDir","Date","now","connect","isLocked","SenseError","store","Math","round","Promise","resolve","setTimeout","connectWithDialect","stateDir","handle","conn","closed","builder","version","features","wantFeatures","forcedPaths","embedInvalidate","featureToggles","changedKeys","presetForced","embedKind","toggles","changed","recordedMaxMs","embedParsed","featureParsed","parsed","warnings","stages","join","STATE_DIR","mkdirSync","recursive","filename","createBuilder","reconcileDialect","exec","getMeta","featureSignature","FEATURES","schemaVersion","console","error","close","clearCache","changedSignatureKeys","isPresetOnlyChange","forcedPresetPaths","size","has","classifyEmbedChange","isFeatureOnlyChange","classifyFeatureToggles","embedIdentityAdopted","setMeta","signatureDiff","ensureSchema","setDerivedBusyTimeout","Number","min","max","invalidate","invalidateFeatures","build","resolvedCfg","createStore","rekeyChunkText","stmt","prepare","get","n"],"mappings":"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"}
@@ -1,8 +1,10 @@
1
1
  import type { Config } from '../config/index.js';
2
2
  import type { ParsePool } from '../scan/pool.js';
3
+ import { type Stages } from './stages.js';
3
4
  import type { Connection, ReconcileDialect } from './types.js';
4
5
  export declare const CORE_FRONTMATTER_COLUMNS: Set<string>;
5
6
  export declare function reconcile(conn: Connection, cfg: Config, baseDir: string, dialect: ReconcileDialect, pool?: ParsePool, forcedPaths?: ReadonlySet<string>): Promise<{
6
7
  parsed: number;
7
8
  warnings: string[];
9
+ stages: Stages;
8
10
  }>;
@@ -1,8 +1,10 @@
1
1
  import type { Config } from '../config/index.js';
2
2
  import type { ParsePool } from '../scan/pool.js';
3
+ import { type Stages } from './stages.js';
3
4
  import type { Connection, ReconcileDialect } from './types.js';
4
5
  export declare const CORE_FRONTMATTER_COLUMNS: Set<string>;
5
6
  export declare function reconcile(conn: Connection, cfg: Config, baseDir: string, dialect: ReconcileDialect, pool?: ParsePool, forcedPaths?: ReadonlySet<string>): Promise<{
6
7
  parsed: number;
7
8
  warnings: string[];
9
+ stages: Stages;
8
10
  }>;