sensemaking 0.24.6 → 0.25.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 (249) hide show
  1. package/README.md +20 -11
  2. package/dist/cjs/cli/build.d.cts +3 -0
  3. package/dist/cjs/cli/build.d.ts +3 -0
  4. package/dist/cjs/cli/build.js +195 -0
  5. package/dist/cjs/cli/build.js.map +1 -0
  6. package/dist/cjs/cli/index.d.cts +7 -6
  7. package/dist/cjs/cli/index.d.ts +7 -6
  8. package/dist/cjs/cli/index.js +12 -6
  9. package/dist/cjs/cli/index.js.map +1 -1
  10. package/dist/cjs/cli/init.js +2 -2
  11. package/dist/cjs/cli/init.js.map +1 -1
  12. package/dist/cjs/cli/map.js +7 -2
  13. package/dist/cjs/cli/map.js.map +1 -1
  14. package/dist/cjs/cli/named.js +63 -21
  15. package/dist/cjs/cli/named.js.map +1 -1
  16. package/dist/cjs/cli/path.js +7 -2
  17. package/dist/cjs/cli/path.js.map +1 -1
  18. package/dist/cjs/cli/peek.js +7 -2
  19. package/dist/cjs/cli/peek.js.map +1 -1
  20. package/dist/cjs/cli/related.js +55 -6
  21. package/dist/cjs/cli/related.js.map +1 -1
  22. package/dist/cjs/cli/search.js +54 -15
  23. package/dist/cjs/cli/search.js.map +1 -1
  24. package/dist/cjs/cli/shared.d.cts +9 -3
  25. package/dist/cjs/cli/shared.d.ts +9 -3
  26. package/dist/cjs/cli/shared.js +109 -74
  27. package/dist/cjs/cli/shared.js.map +1 -1
  28. package/dist/cjs/cli/sql.js +8 -3
  29. package/dist/cjs/cli/sql.js.map +1 -1
  30. package/dist/cjs/cli/status.js +142 -50
  31. package/dist/cjs/cli/status.js.map +1 -1
  32. package/dist/cjs/cli/types.d.cts +4 -2
  33. package/dist/cjs/cli/types.d.ts +4 -2
  34. package/dist/cjs/cli.js +10 -4
  35. package/dist/cjs/cli.js.map +1 -1
  36. package/dist/cjs/commands/map.js +10 -6
  37. package/dist/cjs/commands/map.js.map +1 -1
  38. package/dist/cjs/commands/peek.js +10 -6
  39. package/dist/cjs/commands/peek.js.map +1 -1
  40. package/dist/cjs/commands/related.d.cts +1 -0
  41. package/dist/cjs/commands/related.d.ts +1 -0
  42. package/dist/cjs/commands/related.js +56 -21
  43. package/dist/cjs/commands/related.js.map +1 -1
  44. package/dist/cjs/commands/scope.js +1 -1
  45. package/dist/cjs/commands/scope.js.map +1 -1
  46. package/dist/cjs/commands/search.js +102 -84
  47. package/dist/cjs/commands/search.js.map +1 -1
  48. package/dist/cjs/config/index.d.cts +1 -1
  49. package/dist/cjs/config/index.d.ts +1 -1
  50. package/dist/cjs/config/index.js.map +1 -1
  51. package/dist/cjs/config/load.d.cts +6 -1
  52. package/dist/cjs/config/load.d.ts +6 -1
  53. package/dist/cjs/config/load.js +38 -1
  54. package/dist/cjs/config/load.js.map +1 -1
  55. package/dist/cjs/config/types.d.cts +2 -1
  56. package/dist/cjs/config/types.d.ts +2 -1
  57. package/dist/cjs/config/types.js +1 -1
  58. package/dist/cjs/config/types.js.map +1 -1
  59. package/dist/cjs/config/validate.js +20 -0
  60. package/dist/cjs/config/validate.js.map +1 -1
  61. package/dist/cjs/embed/query.d.cts +2 -1
  62. package/dist/cjs/embed/query.d.ts +2 -1
  63. package/dist/cjs/embed/query.js +186 -109
  64. package/dist/cjs/embed/query.js.map +1 -1
  65. package/dist/cjs/errors.d.cts +1 -1
  66. package/dist/cjs/errors.d.ts +1 -1
  67. package/dist/cjs/errors.js.map +1 -1
  68. package/dist/cjs/features/embed.js.map +1 -1
  69. package/dist/cjs/graph/traverse.js +11 -6
  70. package/dist/cjs/graph/traverse.js.map +1 -1
  71. package/dist/cjs/index.d.cts +3 -3
  72. package/dist/cjs/index.d.ts +3 -3
  73. package/dist/cjs/index.js +3 -0
  74. package/dist/cjs/index.js.map +1 -1
  75. package/dist/cjs/lib/atomic-write.js +20 -6
  76. package/dist/cjs/lib/atomic-write.js.map +1 -1
  77. package/dist/cjs/lib/serial-query.d.cts +1 -0
  78. package/dist/cjs/lib/serial-query.d.ts +1 -0
  79. package/dist/cjs/lib/serial-query.js +22 -0
  80. package/dist/cjs/lib/serial-query.js.map +1 -0
  81. package/dist/cjs/scan/index.d.cts +5 -0
  82. package/dist/cjs/scan/index.d.ts +5 -0
  83. package/dist/cjs/scan/index.js +12 -4
  84. package/dist/cjs/scan/index.js.map +1 -1
  85. package/dist/cjs/scan/pool.d.cts +5 -0
  86. package/dist/cjs/scan/pool.d.ts +5 -0
  87. package/dist/cjs/scan/pool.js +167 -55
  88. package/dist/cjs/scan/pool.js.map +1 -1
  89. package/dist/cjs/store/builder.d.cts +6 -1
  90. package/dist/cjs/store/builder.d.ts +6 -1
  91. package/dist/cjs/store/builder.js +135 -5
  92. package/dist/cjs/store/builder.js.map +1 -1
  93. package/dist/cjs/store/duckdb/lexical.d.cts +2 -0
  94. package/dist/cjs/store/duckdb/lexical.d.ts +2 -0
  95. package/dist/cjs/store/duckdb/lexical.js +139 -7
  96. package/dist/cjs/store/duckdb/lexical.js.map +1 -1
  97. package/dist/cjs/store/duckdb/open.d.cts +3 -3
  98. package/dist/cjs/store/duckdb/open.d.ts +3 -3
  99. package/dist/cjs/store/duckdb/open.js +61 -42
  100. package/dist/cjs/store/duckdb/open.js.map +1 -1
  101. package/dist/cjs/store/duckdb/reconcile.js +2 -2
  102. package/dist/cjs/store/duckdb/reconcile.js.map +1 -1
  103. package/dist/cjs/store/duckdb/vectors.d.cts +1 -0
  104. package/dist/cjs/store/duckdb/vectors.d.ts +1 -0
  105. package/dist/cjs/store/duckdb/vectors.js +55 -43
  106. package/dist/cjs/store/duckdb/vectors.js.map +1 -1
  107. package/dist/cjs/store/index.d.cts +23 -4
  108. package/dist/cjs/store/index.d.ts +23 -4
  109. package/dist/cjs/store/index.js +224 -15
  110. package/dist/cjs/store/index.js.map +1 -1
  111. package/dist/cjs/store/open.d.cts +9 -1
  112. package/dist/cjs/store/open.d.ts +9 -1
  113. package/dist/cjs/store/open.js +479 -128
  114. package/dist/cjs/store/open.js.map +1 -1
  115. package/dist/cjs/store/reconcile.js +93 -63
  116. package/dist/cjs/store/reconcile.js.map +1 -1
  117. package/dist/cjs/store/sqlite/open.d.cts +3 -3
  118. package/dist/cjs/store/sqlite/open.d.ts +3 -3
  119. package/dist/cjs/store/sqlite/open.js +44 -36
  120. package/dist/cjs/store/sqlite/open.js.map +1 -1
  121. package/dist/cjs/store/turso/open.d.cts +3 -3
  122. package/dist/cjs/store/turso/open.d.ts +3 -3
  123. package/dist/cjs/store/turso/open.js +83 -66
  124. package/dist/cjs/store/turso/open.js.map +1 -1
  125. package/dist/cjs/store/turso/store.d.cts +3 -1
  126. package/dist/cjs/store/turso/store.d.ts +3 -1
  127. package/dist/cjs/store/turso/store.js +46 -31
  128. package/dist/cjs/store/turso/store.js.map +1 -1
  129. package/dist/cjs/store/types.d.cts +12 -3
  130. package/dist/cjs/store/types.d.ts +12 -3
  131. package/dist/cjs/store/types.js.map +1 -1
  132. package/dist/cjs/watch.js +155 -35
  133. package/dist/cjs/watch.js.map +1 -1
  134. package/dist/esm/cli/build.d.ts +3 -0
  135. package/dist/esm/cli/build.js +18 -0
  136. package/dist/esm/cli/build.js.map +1 -0
  137. package/dist/esm/cli/index.d.ts +7 -6
  138. package/dist/esm/cli/index.js +8 -6
  139. package/dist/esm/cli/index.js.map +1 -1
  140. package/dist/esm/cli/init.js +2 -2
  141. package/dist/esm/cli/init.js.map +1 -1
  142. package/dist/esm/cli/map.js +8 -2
  143. package/dist/esm/cli/map.js.map +1 -1
  144. package/dist/esm/cli/named.js +38 -14
  145. package/dist/esm/cli/named.js.map +1 -1
  146. package/dist/esm/cli/path.js +8 -2
  147. package/dist/esm/cli/path.js.map +1 -1
  148. package/dist/esm/cli/peek.js +8 -2
  149. package/dist/esm/cli/peek.js.map +1 -1
  150. package/dist/esm/cli/related.js +21 -3
  151. package/dist/esm/cli/related.js.map +1 -1
  152. package/dist/esm/cli/search.js +28 -7
  153. package/dist/esm/cli/search.js.map +1 -1
  154. package/dist/esm/cli/shared.d.ts +9 -3
  155. package/dist/esm/cli/shared.js +44 -24
  156. package/dist/esm/cli/shared.js.map +1 -1
  157. package/dist/esm/cli/sql.js +8 -2
  158. package/dist/esm/cli/sql.js.map +1 -1
  159. package/dist/esm/cli/status.js +166 -111
  160. package/dist/esm/cli/status.js.map +1 -1
  161. package/dist/esm/cli/types.d.ts +4 -2
  162. package/dist/esm/cli/types.js.map +1 -1
  163. package/dist/esm/cli.js +9 -4
  164. package/dist/esm/cli.js.map +1 -1
  165. package/dist/esm/commands/map.js +5 -1
  166. package/dist/esm/commands/map.js.map +1 -1
  167. package/dist/esm/commands/peek.js +5 -1
  168. package/dist/esm/commands/peek.js.map +1 -1
  169. package/dist/esm/commands/related.d.ts +1 -0
  170. package/dist/esm/commands/related.js +19 -10
  171. package/dist/esm/commands/related.js.map +1 -1
  172. package/dist/esm/commands/scope.js +1 -1
  173. package/dist/esm/commands/scope.js.map +1 -1
  174. package/dist/esm/commands/search.js +11 -10
  175. package/dist/esm/commands/search.js.map +1 -1
  176. package/dist/esm/config/index.d.ts +1 -1
  177. package/dist/esm/config/index.js.map +1 -1
  178. package/dist/esm/config/load.d.ts +6 -1
  179. package/dist/esm/config/load.js +32 -3
  180. package/dist/esm/config/load.js.map +1 -1
  181. package/dist/esm/config/types.d.ts +2 -1
  182. package/dist/esm/config/types.js +1 -1
  183. package/dist/esm/config/types.js.map +1 -1
  184. package/dist/esm/config/validate.js +20 -0
  185. package/dist/esm/config/validate.js.map +1 -1
  186. package/dist/esm/embed/query.d.ts +2 -1
  187. package/dist/esm/embed/query.js +40 -34
  188. package/dist/esm/embed/query.js.map +1 -1
  189. package/dist/esm/errors.d.ts +1 -1
  190. package/dist/esm/errors.js.map +1 -1
  191. package/dist/esm/features/embed.js.map +1 -1
  192. package/dist/esm/graph/traverse.js +5 -1
  193. package/dist/esm/graph/traverse.js.map +1 -1
  194. package/dist/esm/index.d.ts +3 -3
  195. package/dist/esm/index.js +1 -1
  196. package/dist/esm/index.js.map +1 -1
  197. package/dist/esm/lib/atomic-write.js +14 -6
  198. package/dist/esm/lib/atomic-write.js.map +1 -1
  199. package/dist/esm/lib/serial-query.d.ts +1 -0
  200. package/dist/esm/lib/serial-query.js +13 -0
  201. package/dist/esm/lib/serial-query.js.map +1 -0
  202. package/dist/esm/scan/index.d.ts +5 -0
  203. package/dist/esm/scan/index.js +7 -3
  204. package/dist/esm/scan/index.js.map +1 -1
  205. package/dist/esm/scan/pool.d.ts +5 -0
  206. package/dist/esm/scan/pool.js +41 -16
  207. package/dist/esm/scan/pool.js.map +1 -1
  208. package/dist/esm/store/builder.d.ts +6 -1
  209. package/dist/esm/store/builder.js +19 -0
  210. package/dist/esm/store/builder.js.map +1 -1
  211. package/dist/esm/store/duckdb/lexical.d.ts +2 -0
  212. package/dist/esm/store/duckdb/lexical.js +32 -4
  213. package/dist/esm/store/duckdb/lexical.js.map +1 -1
  214. package/dist/esm/store/duckdb/open.d.ts +3 -3
  215. package/dist/esm/store/duckdb/open.js +16 -7
  216. package/dist/esm/store/duckdb/open.js.map +1 -1
  217. package/dist/esm/store/duckdb/reconcile.js +2 -2
  218. package/dist/esm/store/duckdb/reconcile.js.map +1 -1
  219. package/dist/esm/store/duckdb/vectors.d.ts +1 -0
  220. package/dist/esm/store/duckdb/vectors.js +18 -14
  221. package/dist/esm/store/duckdb/vectors.js.map +1 -1
  222. package/dist/esm/store/index.d.ts +23 -4
  223. package/dist/esm/store/index.js +80 -15
  224. package/dist/esm/store/index.js.map +1 -1
  225. package/dist/esm/store/open.d.ts +9 -1
  226. package/dist/esm/store/open.js +175 -84
  227. package/dist/esm/store/open.js.map +1 -1
  228. package/dist/esm/store/reconcile.js +12 -0
  229. package/dist/esm/store/reconcile.js.map +1 -1
  230. package/dist/esm/store/sqlite/open.d.ts +3 -3
  231. package/dist/esm/store/sqlite/open.js +9 -6
  232. package/dist/esm/store/sqlite/open.js.map +1 -1
  233. package/dist/esm/store/turso/open.d.ts +3 -3
  234. package/dist/esm/store/turso/open.js +14 -10
  235. package/dist/esm/store/turso/open.js.map +1 -1
  236. package/dist/esm/store/turso/store.d.ts +3 -1
  237. package/dist/esm/store/turso/store.js +5 -1
  238. package/dist/esm/store/turso/store.js.map +1 -1
  239. package/dist/esm/store/types.d.ts +12 -3
  240. package/dist/esm/store/types.js.map +1 -1
  241. package/dist/esm/watch.js +57 -19
  242. package/dist/esm/watch.js.map +1 -1
  243. package/package.json +1 -1
  244. package/schema.json +7 -2
  245. package/skills/sense/SKILL.md +3 -3
  246. package/skills/sense-bases/SKILL.md +1 -2
  247. package/skills/sense-setup/SKILL.md +1 -1
  248. package/skills/sense-setup/references/embeddings.md +1 -1
  249. package/skills/sense-setup/references/store-benchmarks.md +6 -6
@@ -9,6 +9,9 @@ function _export(target, all) {
9
9
  });
10
10
  }
11
11
  _export(exports, {
12
+ get createVectorWriteStage () {
13
+ return createVectorWriteStage;
14
+ },
12
15
  get scanCandidates () {
13
16
  return scanCandidates;
14
17
  },
@@ -21,7 +24,6 @@ _export(exports, {
21
24
  });
22
25
  var _transactionts = require("../transaction.js");
23
26
  var _vectorsts = require("../vectors.js");
24
- var _batchts = require("./batch.js");
25
27
  var _nativets = require("./native.js");
26
28
  function _array_like_to_array(arr, len) {
27
29
  if (len == null || len > arr.length) len = arr.length;
@@ -182,6 +184,25 @@ function _unsupported_iterable_to_array(o, minLen) {
182
184
  // A bind position whose type is left to auto-inference (safe for plain strings/numbers; only
183
185
  // the vector ARRAY positions below need an explicit type -- see writeVectorBatch's comment).
184
186
  var untyped = undefined;
187
+ var VECTOR_WRITE_STAGE = '_sense_vector_write_stage';
188
+ function createVectorWriteStage(duckdb, dims) {
189
+ return _async_to_generator(function() {
190
+ return _ts_generator(this, function(_state) {
191
+ switch(_state.label){
192
+ case 0:
193
+ return [
194
+ 4,
195
+ duckdb.run("CREATE TEMP TABLE ".concat(VECTOR_WRITE_STAGE, ' ("path" TEXT, chunk INTEGER, vector FLOAT[').concat(dims, "])"))
196
+ ];
197
+ case 1:
198
+ _state.sent();
199
+ return [
200
+ 2
201
+ ];
202
+ }
203
+ });
204
+ })();
205
+ }
185
206
  // The DDL-fixed array width can exceed a vector's actual length (a hypothetical model sliced under the column's width);
186
207
  // zero-padding leaves cosine scores unchanged since the added dimensions contribute nothing to either vector's dot product or norm.
187
208
  function padded(values, dims) {
@@ -206,7 +227,7 @@ function dequantize(row, dims) {
206
227
  }
207
228
  function writeVectorBatch(duckdb, conn, dims, rows) {
208
229
  return _async_to_generator(function() {
209
- var _ref, arrayValue, ARRAY, DOUBLE, rewritten;
230
+ var _ref, ARRAY, FLOAT, vectorType;
210
231
  return _ts_generator(this, function(_state) {
211
232
  switch(_state.label){
212
233
  case 0:
@@ -218,71 +239,62 @@ function writeVectorBatch(duckdb, conn, dims, rows) {
218
239
  (0, _nativets.duckdbApi)()
219
240
  ];
220
241
  case 1:
221
- _ref = _state.sent(), arrayValue = _ref.arrayValue, ARRAY = _ref.ARRAY, DOUBLE = _ref.DOUBLE;
222
- rewritten = (0, _batchts.rewriteUpdate)('UPDATE embeddings SET vector = ? WHERE "path" = ? AND chunk = ?', rows.length);
223
- if (!rewritten) throw new Error('duckdb: writeVectorBatch SQL shape not recognized by rewriteUpdate');
242
+ _ref = _state.sent(), ARRAY = _ref.ARRAY, FLOAT = _ref.FLOAT;
243
+ vectorType = ARRAY(FLOAT, dims);
224
244
  return [
225
245
  4,
226
246
  (0, _transactionts.withTransaction)(conn, function() {
227
247
  return _async_to_generator(function() {
228
- var stmt, values, types, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, row;
248
+ var appender, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, row;
229
249
  return _ts_generator(this, function(_state) {
230
250
  switch(_state.label){
231
251
  case 0:
232
252
  return [
233
253
  4,
234
- duckdb.prepare(rewritten.sql)
254
+ duckdb.run("DELETE FROM ".concat(VECTOR_WRITE_STAGE))
235
255
  ];
236
256
  case 1:
237
- stmt = _state.sent();
238
- _state.label = 2;
239
- case 2:
240
- _state.trys.push([
241
- 2,
242
- ,
257
+ _state.sent();
258
+ return [
243
259
  4,
244
- 5
245
- ]);
246
- values = [];
247
- types = [];
248
- _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
260
+ duckdb.createAppender(VECTOR_WRITE_STAGE)
261
+ ];
262
+ case 2:
263
+ appender = _state.sent();
249
264
  try {
250
- for(_iterator = rows[Symbol.iterator](); !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
251
- row = _step.value;
252
- values.push(arrayValue(dequantize(row, dims)), row.path, row.chunk);
253
- types.push(ARRAY(DOUBLE, dims), untyped, untyped);
254
- }
255
- } catch (err) {
256
- _didIteratorError = true;
257
- _iteratorError = err;
258
- } finally{
265
+ _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
259
266
  try {
260
- if (!_iteratorNormalCompletion && _iterator.return != null) {
261
- _iterator.return();
267
+ for(_iterator = rows[Symbol.iterator](); !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
268
+ row = _step.value;
269
+ appender.appendVarchar(row.path);
270
+ appender.appendInteger(row.chunk);
271
+ appender.appendArray(dequantize(row, dims), vectorType);
272
+ appender.endRow();
262
273
  }
274
+ } catch (err) {
275
+ _didIteratorError = true;
276
+ _iteratorError = err;
263
277
  } finally{
264
- if (_didIteratorError) {
265
- throw _iteratorError;
278
+ try {
279
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
280
+ _iterator.return();
281
+ }
282
+ } finally{
283
+ if (_didIteratorError) {
284
+ throw _iteratorError;
285
+ }
266
286
  }
267
287
  }
288
+ appender.flushSync();
289
+ } finally{
290
+ appender.closeSync();
268
291
  }
269
- stmt.bind(values, types);
270
292
  return [
271
293
  4,
272
- stmt.run()
294
+ duckdb.run("UPDATE embeddings SET vector = staged.vector FROM ".concat(VECTOR_WRITE_STAGE, ' AS staged WHERE embeddings."path" = staged."path" AND embeddings.chunk = staged.chunk'))
273
295
  ];
274
296
  case 3:
275
297
  _state.sent();
276
- return [
277
- 3,
278
- 5
279
- ];
280
- case 4:
281
- stmt.destroySync();
282
- return [
283
- 7
284
- ];
285
- case 5:
286
298
  return [
287
299
  2
288
300
  ];
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/duckdb/vectors.ts"],"sourcesContent":["import type { DuckDBConnection, DuckDBType, DuckDBValue } from '@duckdb/node-api';\nimport { withTransaction } from '../transaction.ts';\nimport type { Connection, VectorCandidate, VectorSimilar, VectorWriteRow } from '../types.ts';\nimport { asCosine, sampleEvenly } from '../vectors.ts';\nimport { rewriteUpdate } from './batch.ts';\nimport { duckdbApi } from './native.ts';\n\n// This store keeps vectors as native FLOAT[dims] arrays (dims fixed at DDL time by open.ts's ensureSchema, from embed/types.ts's STORE_DIMS) and\n// scans them with array_cosine_similarity, pushing top-k into SQL instead of pulling every row into JS; sqlite's int8+scale BLOB scan is its own representation. Every function here takes `dims` as a parameter rather than importing STORE_DIMS directly, so it stays testable at any width.\n\n// A value import of '@duckdb/node-api' must never sit at module top level, or a sqlite-only tree would resolve this optional dependency\n// just by importing store/index.ts; native.ts's shared duckdbApi() keeps that lazy and reuses whatever open.ts already resolved.\n\n// A bind position whose type is left to auto-inference (safe for plain strings/numbers; only\n// the vector ARRAY positions below need an explicit type -- see writeVectorBatch's comment).\nconst untyped = undefined as unknown as DuckDBType;\n\n// The DDL-fixed array width can exceed a vector's actual length (a hypothetical model sliced under the column's width);\n// zero-padding leaves cosine scores unchanged since the added dimensions contribute nothing to either vector's dot product or norm.\nfunction padded(values: ArrayLike<number>, dims: number): number[] {\n const out = new Array<number>(dims).fill(0);\n for (let d = 0; d < Math.min(values.length, dims); d++) out[d] = values[d];\n return out;\n}\n\nfunction inClause(column: string, count: number): string {\n return `${column} IN (${Array.from({ length: count }, () => '?').join(', ')})`;\n}\n\n// Rows arrive int8-quantized with a per-vector scale (the wire format embed/query.ts produces for every store, see toStore);\n// dequantizing into a plain float array is this store's own representation choice, so both stores are handed the same vectors and diverge only here.\nfunction dequantize(row: VectorWriteRow, dims: number): number[] {\n const q = new Int8Array(row.vector.buffer, row.vector.byteOffset, row.vector.byteLength);\n return padded(\n Array.from(q, (v) => v * row.scale),\n dims\n );\n}\n\n// One runBatch-equivalent call per provider batch: a single multi-row UPDATE (batch.ts's rewriteUpdate), bound directly against the\n// native connection because the vector column needs an explicit ARRAY(DOUBLE, dims) bind type -- auto inference misreads an all-integer first component as INTEGER and silently truncates the rest (verified live: an untyped bind of [0, 0.35, 0.1, -0.2] stores [0,0,0,0]).\nexport async function writeVectorBatch(duckdb: DuckDBConnection, conn: Connection, dims: number, rows: VectorWriteRow[]): Promise<void> {\n if (rows.length === 0) return;\n const { arrayValue, ARRAY, DOUBLE } = await duckdbApi();\n const rewritten = rewriteUpdate('UPDATE embeddings SET vector = ? WHERE \"path\" = ? AND chunk = ?', rows.length);\n if (!rewritten) throw new Error('duckdb: writeVectorBatch SQL shape not recognized by rewriteUpdate');\n\n await withTransaction(conn, async () => {\n const stmt = await duckdb.prepare(rewritten.sql);\n try {\n const values: DuckDBValue[] = [];\n const types: DuckDBType[] = [];\n for (const row of rows) {\n values.push(arrayValue(dequantize(row, dims)), row.path, row.chunk);\n types.push(ARRAY(DOUBLE, dims), untyped, untyped);\n }\n stmt.bind(values, types);\n await stmt.run();\n } finally {\n stmt.destroySync();\n }\n });\n}\n\n// Best chunk per file by cosine, with the earliest chunk winning exact score ties.\n// An empty `allowed` set matches sqlite's scan (every row filtered out) without touching the table.\nexport async function scanCandidates(duckdb: DuckDBConnection, qv: Float32Array, dims: number, fetch: number, allowed?: Set<string>): Promise<VectorCandidate[]> {\n if (allowed && allowed.size === 0) return [];\n const { arrayValue, ARRAY, DOUBLE } = await duckdbApi();\n const allowedList = allowed ? [...allowed] : [];\n const query = padded(qv, dims);\n const queryNorm = Math.sqrt(query.reduce((sum, value) => sum + value * value, 0));\n const score = queryNorm === 0 ? '0.0' : 'CASE WHEN array_inner_product(vector, vector) = 0 THEN 0.0 ELSE array_cosine_similarity(vector, ?) END';\n const sql = `SELECT \"path\", start_line, end_line, score\n FROM (\n SELECT \"path\", start_line, end_line, score,\n row_number() OVER (PARTITION BY \"path\" ORDER BY score DESC, chunk ASC) AS selected\n FROM (\n SELECT \"path\", chunk, start_line, end_line, ${score} AS score\n FROM embeddings\n WHERE vector IS NOT NULL ${allowed ? `AND ${inClause('\"path\"', allowedList.length)}` : ''}\n ) sub\n ) ranked\n WHERE selected = 1\n ORDER BY score DESC, \"path\" ASC\n LIMIT ?`;\n const stmt = await duckdb.prepare(sql);\n try {\n const values: DuckDBValue[] = [...(queryNorm === 0 ? [] : [arrayValue(query)]), ...allowedList, fetch];\n const types: DuckDBType[] = [...(queryNorm === 0 ? [] : [ARRAY(DOUBLE, dims)]), ...allowedList.map(() => untyped), untyped];\n stmt.bind(values, types);\n const reader = await stmt.runAndReadAll();\n const rows = reader.getRowObjectsJS() as Array<{ path: string; start_line: number; end_line: number; score: number }>;\n return rows.map((r) => ({ path: r.path, lines: `L${r.start_line}-${r.end_line}`, similarity: asCosine(r.score) }));\n } finally {\n stmt.destroySync();\n }\n}\n\n// Note-to-note similarity is the max cosine over (target chunk, other chunk) pairs, pushed into one native scan: the sampled target vectors become\n// a small VALUES list, cross-joined against every stored vector and reduced with max()/GROUP BY, so the O(target x stored) cost (12.7s at 201 chunks/note in JS) runs vectorized instead of scalar.\nexport async function scanSimilar(duckdb: DuckDBConnection, conn: Connection, dims: number, path: string, opts: { exclude: Set<string>; allowed?: Set<string>; k: number }): Promise<VectorSimilar[]> {\n if (opts.allowed && opts.allowed.size === 0) return [];\n const targetStmt = await conn.prepare('SELECT vector FROM embeddings WHERE \"path\" = ? AND vector IS NOT NULL ORDER BY chunk');\n const targetRows = (await targetStmt.all(path)) as Array<{ vector: number[] }>;\n if (targetRows.length === 0) return [];\n const targets = sampleEvenly(targetRows).map((row) => row.vector);\n\n const { arrayValue, ARRAY, DOUBLE } = await duckdbApi();\n const excludeList = [...opts.exclude];\n const allowedList = opts.allowed ? [...opts.allowed] : [];\n const sql = `WITH targets(tv) AS (VALUES ${targets.map(() => '(?)').join(', ')}), grouped AS (\n SELECT e.\"path\" AS path, max(CASE WHEN array_inner_product(e.vector, e.vector) = 0 OR array_inner_product(t.tv, t.tv) = 0 THEN 0.0 ELSE array_cosine_similarity(e.vector, t.tv) END) AS score\n FROM embeddings e, targets t\n WHERE e.vector IS NOT NULL AND e.\"path\" != ?\n ${excludeList.length > 0 ? `AND NOT ${inClause('e.\"path\"', excludeList.length)}` : ''}\n ${opts.allowed ? `AND ${inClause('e.\"path\"', allowedList.length)}` : ''}\n GROUP BY e.\"path\"\n )\n SELECT path, score FROM grouped\n ORDER BY score DESC, path ASC\n LIMIT ?`;\n const stmt = await duckdb.prepare(sql);\n try {\n const values: DuckDBValue[] = [...targets.map((t) => arrayValue(padded(t, dims))), path, ...excludeList, ...allowedList, opts.k];\n const types: DuckDBType[] = [...targets.map(() => ARRAY(DOUBLE, dims)), untyped, ...excludeList.map(() => untyped), ...allowedList.map(() => untyped), untyped];\n stmt.bind(values, types);\n const reader = await stmt.runAndReadAll();\n const rows = reader.getRowObjectsJS() as Array<{ path: string; score: number }>;\n return rows.map((r) => ({ path: r.path, similarity: asCosine(r.score) }));\n } finally {\n stmt.destroySync();\n }\n}\n"],"names":["scanCandidates","scanSimilar","writeVectorBatch","untyped","undefined","padded","values","dims","out","Array","fill","d","Math","min","length","inClause","column","count","from","join","dequantize","row","q","Int8Array","vector","buffer","byteOffset","byteLength","v","scale","duckdb","conn","rows","arrayValue","ARRAY","DOUBLE","rewritten","duckdbApi","rewriteUpdate","Error","withTransaction","stmt","types","prepare","sql","push","path","chunk","bind","run","destroySync","qv","fetch","allowed","allowedList","query","queryNorm","score","reader","size","sqrt","reduce","sum","value","map","runAndReadAll","getRowObjectsJS","r","lines","start_line","end_line","similarity","asCosine","opts","targetStmt","targetRows","targets","excludeList","all","sampleEvenly","exclude","t","k"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/duckdb/vectors.ts"],"sourcesContent":["import type { DuckDBConnection, DuckDBType, DuckDBValue } from '@duckdb/node-api';\nimport { withTransaction } from '../transaction.ts';\nimport type { Connection, VectorCandidate, VectorSimilar, VectorWriteRow } from '../types.ts';\nimport { asCosine, sampleEvenly } from '../vectors.ts';\nimport { duckdbApi } from './native.ts';\n\n// This store keeps vectors as native FLOAT[dims] arrays (dims fixed at DDL time by open.ts's ensureSchema, from embed/types.ts's STORE_DIMS) and\n// scans them with array_cosine_similarity, pushing top-k into SQL instead of pulling every row into JS; sqlite's int8+scale BLOB scan is its own representation. Every function here takes `dims` as a parameter rather than importing STORE_DIMS directly, so it stays testable at any width.\n\n// A value import of '@duckdb/node-api' must never sit at module top level, or a sqlite-only tree would resolve this optional dependency\n// just by importing store/index.ts; native.ts's shared duckdbApi() keeps that lazy and reuses whatever open.ts already resolved.\n\n// A bind position whose type is left to auto-inference (safe for plain strings/numbers; only\n// the vector ARRAY positions below need an explicit type -- see writeVectorBatch's comment).\nconst untyped = undefined as unknown as DuckDBType;\nconst VECTOR_WRITE_STAGE = '_sense_vector_write_stage';\n\n// Created once per native connection outside write transactions; its lifetime follows that connection.\nexport async function createVectorWriteStage(duckdb: DuckDBConnection, dims: number): Promise<void> {\n await duckdb.run(`CREATE TEMP TABLE ${VECTOR_WRITE_STAGE} (\"path\" TEXT, chunk INTEGER, vector FLOAT[${dims}])`);\n}\n\n// The DDL-fixed array width can exceed a vector's actual length (a hypothetical model sliced under the column's width);\n// zero-padding leaves cosine scores unchanged since the added dimensions contribute nothing to either vector's dot product or norm.\nfunction padded(values: ArrayLike<number>, dims: number): number[] {\n const out = new Array<number>(dims).fill(0);\n for (let d = 0; d < Math.min(values.length, dims); d++) out[d] = values[d];\n return out;\n}\n\nfunction inClause(column: string, count: number): string {\n return `${column} IN (${Array.from({ length: count }, () => '?').join(', ')})`;\n}\n\n// Rows arrive int8-quantized with a per-vector scale (the wire format embed/query.ts produces for every store, see toStore);\n// dequantizing into a plain float array is this store's own representation choice, so both stores are handed the same vectors and diverge only here.\nfunction dequantize(row: VectorWriteRow, dims: number): number[] {\n const q = new Int8Array(row.vector.buffer, row.vector.byteOffset, row.vector.byteLength);\n return padded(\n Array.from(q, (v) => v * row.scale),\n dims\n );\n}\n\n// The native appender needs an explicit FLOAT array type: inference from an integer first component\n// silently truncates fractional components. The fixed UPDATE keeps each provider batch keyed by path and chunk.\nexport async function writeVectorBatch(duckdb: DuckDBConnection, conn: Connection, dims: number, rows: VectorWriteRow[]): Promise<void> {\n if (rows.length === 0) return;\n const { ARRAY, FLOAT } = await duckdbApi();\n const vectorType = ARRAY(FLOAT, dims);\n\n await withTransaction(conn, async () => {\n await duckdb.run(`DELETE FROM ${VECTOR_WRITE_STAGE}`);\n const appender = await duckdb.createAppender(VECTOR_WRITE_STAGE);\n try {\n for (const row of rows) {\n appender.appendVarchar(row.path);\n appender.appendInteger(row.chunk);\n appender.appendArray(dequantize(row, dims), vectorType);\n appender.endRow();\n }\n appender.flushSync();\n } finally {\n appender.closeSync();\n }\n await duckdb.run(`UPDATE embeddings SET vector = staged.vector FROM ${VECTOR_WRITE_STAGE} AS staged WHERE embeddings.\"path\" = staged.\"path\" AND embeddings.chunk = staged.chunk`);\n });\n}\n\n// Best chunk per file by cosine, with the earliest chunk winning exact score ties.\n// An empty `allowed` set matches sqlite's scan (every row filtered out) without touching the table.\nexport async function scanCandidates(duckdb: DuckDBConnection, qv: Float32Array, dims: number, fetch: number, allowed?: Set<string>): Promise<VectorCandidate[]> {\n if (allowed && allowed.size === 0) return [];\n const { arrayValue, ARRAY, DOUBLE } = await duckdbApi();\n const allowedList = allowed ? [...allowed] : [];\n const query = padded(qv, dims);\n const queryNorm = Math.sqrt(query.reduce((sum, value) => sum + value * value, 0));\n const score = queryNorm === 0 ? '0.0' : 'CASE WHEN array_inner_product(vector, vector) = 0 THEN 0.0 ELSE array_cosine_similarity(vector, ?) END';\n const sql = `SELECT \"path\", start_line, end_line, score\n FROM (\n SELECT \"path\", start_line, end_line, score,\n row_number() OVER (PARTITION BY \"path\" ORDER BY score DESC, chunk ASC) AS selected\n FROM (\n SELECT \"path\", chunk, start_line, end_line, ${score} AS score\n FROM embeddings\n WHERE vector IS NOT NULL ${allowed ? `AND ${inClause('\"path\"', allowedList.length)}` : ''}\n ) sub\n ) ranked\n WHERE selected = 1\n ORDER BY score DESC, \"path\" ASC\n LIMIT ?`;\n const stmt = await duckdb.prepare(sql);\n try {\n const values: DuckDBValue[] = [...(queryNorm === 0 ? [] : [arrayValue(query)]), ...allowedList, fetch];\n const types: DuckDBType[] = [...(queryNorm === 0 ? [] : [ARRAY(DOUBLE, dims)]), ...allowedList.map(() => untyped), untyped];\n stmt.bind(values, types);\n const reader = await stmt.runAndReadAll();\n const rows = reader.getRowObjectsJS() as Array<{ path: string; start_line: number; end_line: number; score: number }>;\n return rows.map((r) => ({ path: r.path, lines: `L${r.start_line}-${r.end_line}`, similarity: asCosine(r.score) }));\n } finally {\n stmt.destroySync();\n }\n}\n\n// Note-to-note similarity is the max cosine over (target chunk, other chunk) pairs, pushed into one native scan: the sampled target vectors become\n// a small VALUES list, cross-joined against every stored vector and reduced with max()/GROUP BY, so the O(target x stored) cost (12.7s at 201 chunks/note in JS) runs vectorized instead of scalar.\nexport async function scanSimilar(duckdb: DuckDBConnection, conn: Connection, dims: number, path: string, opts: { exclude: Set<string>; allowed?: Set<string>; k: number }): Promise<VectorSimilar[]> {\n if (opts.allowed && opts.allowed.size === 0) return [];\n const targetStmt = await conn.prepare('SELECT vector FROM embeddings WHERE \"path\" = ? AND vector IS NOT NULL ORDER BY chunk');\n const targetRows = (await targetStmt.all(path)) as Array<{ vector: number[] }>;\n if (targetRows.length === 0) return [];\n const targets = sampleEvenly(targetRows).map((row) => row.vector);\n\n const { arrayValue, ARRAY, DOUBLE } = await duckdbApi();\n const excludeList = [...opts.exclude];\n const allowedList = opts.allowed ? [...opts.allowed] : [];\n const sql = `WITH targets(tv) AS (VALUES ${targets.map(() => '(?)').join(', ')}), grouped AS (\n SELECT e.\"path\" AS path, max(CASE WHEN array_inner_product(e.vector, e.vector) = 0 OR array_inner_product(t.tv, t.tv) = 0 THEN 0.0 ELSE array_cosine_similarity(e.vector, t.tv) END) AS score\n FROM embeddings e, targets t\n WHERE e.vector IS NOT NULL AND e.\"path\" != ?\n ${excludeList.length > 0 ? `AND NOT ${inClause('e.\"path\"', excludeList.length)}` : ''}\n ${opts.allowed ? `AND ${inClause('e.\"path\"', allowedList.length)}` : ''}\n GROUP BY e.\"path\"\n )\n SELECT path, score FROM grouped\n ORDER BY score DESC, path ASC\n LIMIT ?`;\n const stmt = await duckdb.prepare(sql);\n try {\n const values: DuckDBValue[] = [...targets.map((t) => arrayValue(padded(t, dims))), path, ...excludeList, ...allowedList, opts.k];\n const types: DuckDBType[] = [...targets.map(() => ARRAY(DOUBLE, dims)), untyped, ...excludeList.map(() => untyped), ...allowedList.map(() => untyped), untyped];\n stmt.bind(values, types);\n const reader = await stmt.runAndReadAll();\n const rows = reader.getRowObjectsJS() as Array<{ path: string; score: number }>;\n return rows.map((r) => ({ path: r.path, similarity: asCosine(r.score) }));\n } finally {\n stmt.destroySync();\n }\n}\n"],"names":["createVectorWriteStage","scanCandidates","scanSimilar","writeVectorBatch","untyped","undefined","VECTOR_WRITE_STAGE","duckdb","dims","run","padded","values","out","Array","fill","d","Math","min","length","inClause","column","count","from","join","dequantize","row","q","Int8Array","vector","buffer","byteOffset","byteLength","v","scale","conn","rows","ARRAY","FLOAT","vectorType","duckdbApi","withTransaction","appender","createAppender","appendVarchar","path","appendInteger","chunk","appendArray","endRow","flushSync","closeSync","qv","fetch","allowed","arrayValue","DOUBLE","allowedList","query","queryNorm","score","sql","stmt","types","reader","size","sqrt","reduce","sum","value","prepare","map","bind","runAndReadAll","getRowObjectsJS","r","lines","start_line","end_line","similarity","asCosine","destroySync","opts","targetStmt","targetRows","targets","excludeList","all","sampleEvenly","exclude","t","k"],"mappings":"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"}
@@ -1,11 +1,30 @@
1
1
  import type { ResolvedConfig } from '../config/index.js';
2
- import type { OpenResult } from './open.js';
3
- export declare function openStore(cfg: ResolvedConfig): Promise<OpenResult>;
4
- export { clearCache } from './cache.js';
5
- export type { OpenResult } from './open.js';
2
+ import { clearCache } from './cache.js';
3
+ import type { InternalOpenOptions, OpenOptions, OpenResult } from './open.js';
4
+ import type { Stages } from './stages.js';
5
+ export declare function openStoreFor(cfg: ResolvedConfig, options: InternalOpenOptions): Promise<OpenResult>;
6
+ export declare function openStore(cfg: ResolvedConfig, options?: OpenOptions): Promise<OpenResult>;
7
+ export declare function lexicalReadiness(cfg: ResolvedConfig): Promise<{
8
+ ready: boolean;
9
+ error: string | null;
10
+ }>;
11
+ export interface BuildOptions {
12
+ force?: boolean;
13
+ }
14
+ export interface BuildResult {
15
+ cfg: ResolvedConfig;
16
+ dbPath: string;
17
+ parsed: number;
18
+ warnings: string[];
19
+ stages: Stages;
20
+ }
21
+ export declare function buildIndex(cfg: ResolvedConfig, options?: BuildOptions): Promise<BuildResult>;
22
+ export declare function storeFilename(cfg: ResolvedConfig): string;
23
+ export type { OpenOptions, OpenResult } from './open.js';
6
24
  export { docCount } from './open.js';
7
25
  export { getMeta, setMeta } from './shared.js';
8
26
  export { DB_FILENAME, SCHEMA_VERSION } from './sqlite/open.js';
9
27
  export type { Stages } from './stages.js';
10
28
  export type { Capability, Connection, DocumentStore, LexicalHit, LexicalIndex, LexicalQueryOptions, RawStatement, RunResult, SqlSession, Statement, Store, VectorCandidate, VectorSimilar, VectorStore, VectorWriteRow } from './types.js';
11
29
  export { CAPABILITY_NAMES } from './types.js';
30
+ export { clearCache };
@@ -1,11 +1,30 @@
1
1
  import type { ResolvedConfig } from '../config/index.js';
2
- import type { OpenResult } from './open.js';
3
- export declare function openStore(cfg: ResolvedConfig): Promise<OpenResult>;
4
- export { clearCache } from './cache.js';
5
- export type { OpenResult } from './open.js';
2
+ import { clearCache } from './cache.js';
3
+ import type { InternalOpenOptions, OpenOptions, OpenResult } from './open.js';
4
+ import type { Stages } from './stages.js';
5
+ export declare function openStoreFor(cfg: ResolvedConfig, options: InternalOpenOptions): Promise<OpenResult>;
6
+ export declare function openStore(cfg: ResolvedConfig, options?: OpenOptions): Promise<OpenResult>;
7
+ export declare function lexicalReadiness(cfg: ResolvedConfig): Promise<{
8
+ ready: boolean;
9
+ error: string | null;
10
+ }>;
11
+ export interface BuildOptions {
12
+ force?: boolean;
13
+ }
14
+ export interface BuildResult {
15
+ cfg: ResolvedConfig;
16
+ dbPath: string;
17
+ parsed: number;
18
+ warnings: string[];
19
+ stages: Stages;
20
+ }
21
+ export declare function buildIndex(cfg: ResolvedConfig, options?: BuildOptions): Promise<BuildResult>;
22
+ export declare function storeFilename(cfg: ResolvedConfig): string;
23
+ export type { OpenOptions, OpenResult } from './open.js';
6
24
  export { docCount } from './open.js';
7
25
  export { getMeta, setMeta } from './shared.js';
8
26
  export { DB_FILENAME, SCHEMA_VERSION } from './sqlite/open.js';
9
27
  export type { Stages } from './stages.js';
10
28
  export type { Capability, Connection, DocumentStore, LexicalHit, LexicalIndex, LexicalQueryOptions, RawStatement, RunResult, SqlSession, Statement, Store, VectorCandidate, VectorSimilar, VectorStore, VectorWriteRow } from './types.js';
11
29
  export { CAPABILITY_NAMES } from './types.js';
30
+ export { clearCache };
@@ -1,5 +1,5 @@
1
- // Rows -> a backing store: registry + openStore(cfg). Parsing lives in scan.ts; everything
2
- // beyond frontmatter + content lives in src/features/.
1
+ // Rows -> a backing store: registry + the public open/build boundary. Parsing lives in scan.ts;
2
+ // everything beyond frontmatter + content lives in src/features/.
3
3
  "use strict";
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
@@ -20,6 +20,9 @@ _export(exports, {
20
20
  get SCHEMA_VERSION () {
21
21
  return _opents1.SCHEMA_VERSION;
22
22
  },
23
+ get buildIndex () {
24
+ return buildIndex;
25
+ },
23
26
  get clearCache () {
24
27
  return _cachets.clearCache;
25
28
  },
@@ -29,22 +32,31 @@ _export(exports, {
29
32
  get getMeta () {
30
33
  return _sharedts.getMeta;
31
34
  },
35
+ get lexicalReadiness () {
36
+ return lexicalReadiness;
37
+ },
32
38
  get openStore () {
33
39
  return openStore;
34
40
  },
41
+ get openStoreFor () {
42
+ return openStoreFor;
43
+ },
35
44
  get setMeta () {
36
45
  return _sharedts.setMeta;
46
+ },
47
+ get storeFilename () {
48
+ return storeFilename;
37
49
  }
38
50
  });
39
51
  var _indexts = require("../config/index.js");
40
52
  var _errorsts = require("../errors.js");
53
+ var _cachets = require("./cache.js");
41
54
  var _opents = require("./duckdb/open.js");
42
55
  var _storets = require("./duckdb/store.js");
43
56
  var _opents1 = require("./sqlite/open.js");
44
57
  var _storets1 = require("./sqlite/store.js");
45
58
  var _opents2 = require("./turso/open.js");
46
59
  var _storets2 = require("./turso/store.js");
47
- var _cachets = require("./cache.js");
48
60
  var _opents3 = require("./open.js");
49
61
  var _sharedts = require("./shared.js");
50
62
  var _typests = require("./types.js");
@@ -74,6 +86,48 @@ function _async_to_generator(fn) {
74
86
  });
75
87
  };
76
88
  }
89
+ function _instanceof(left, right) {
90
+ "@swc/helpers - instanceof";
91
+ if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
92
+ return !!right[Symbol.hasInstance](left);
93
+ } else return left instanceof right;
94
+ }
95
+ function _object_without_properties(source, excluded) {
96
+ if (source == null) return {};
97
+ var target = {}, sourceKeys, key, i;
98
+ if (typeof Reflect !== "undefined" && Reflect.ownKeys) {
99
+ sourceKeys = Reflect.ownKeys(Object(source));
100
+ for(i = 0; i < sourceKeys.length; i++){
101
+ key = sourceKeys[i];
102
+ if (excluded.indexOf(key) >= 0) continue;
103
+ if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
104
+ target[key] = source[key];
105
+ }
106
+ return target;
107
+ }
108
+ target = _object_without_properties_loose(source, excluded);
109
+ if (Object.getOwnPropertySymbols) {
110
+ sourceKeys = Object.getOwnPropertySymbols(source);
111
+ for(i = 0; i < sourceKeys.length; i++){
112
+ key = sourceKeys[i];
113
+ if (excluded.indexOf(key) >= 0) continue;
114
+ if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
115
+ target[key] = source[key];
116
+ }
117
+ }
118
+ return target;
119
+ }
120
+ function _object_without_properties_loose(source, excluded) {
121
+ if (source == null) return {};
122
+ var target = {}, sourceKeys = Object.getOwnPropertyNames(source), key, i;
123
+ for(i = 0; i < sourceKeys.length; i++){
124
+ key = sourceKeys[i];
125
+ if (excluded.indexOf(key) >= 0) continue;
126
+ if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
127
+ target[key] = source[key];
128
+ }
129
+ return target;
130
+ }
77
131
  function _ts_generator(thisArg, body) {
78
132
  var f, y, t, _ = {
79
133
  label: 0,
@@ -173,19 +227,20 @@ function _ts_generator(thisArg, body) {
173
227
  };
174
228
  }
175
229
  }
176
- // Capabilities are checked against the registry entry before opening (no wasted connect/reconcile
177
- // work for a config that cannot be satisfied), then the store itself opens.
178
230
  var REGISTRY = {
179
231
  sqlite: {
180
232
  capabilities: _storets1.CAPABILITIES,
233
+ filename: _opents1.DB_FILENAME,
181
234
  open: _opents1.openSqlite
182
235
  },
183
236
  duckdb: {
184
237
  capabilities: _storets.CAPABILITIES,
238
+ filename: _opents.DB_FILENAME,
185
239
  open: _opents.openDuckdb
186
240
  },
187
241
  turso: {
188
242
  capabilities: _storets2.CAPABILITIES,
243
+ filename: _opents2.DB_FILENAME,
189
244
  open: _opents2.openTurso
190
245
  }
191
246
  };
@@ -194,22 +249,176 @@ function entryFor(name) {
194
249
  if (!entry) throw new _errorsts.SenseError('STORE_UNKNOWN', 'unknown backing store "'.concat(name, '"; available: ').concat(Object.keys(REGISTRY).join(', ')));
195
250
  return entry;
196
251
  }
197
- function openStore(cfg) {
252
+ function requirementsFor(cfg) {
253
+ var requirements = new Set([
254
+ 'core',
255
+ 'lexical'
256
+ ]);
257
+ if ((0, _indexts.anyPresetEmbeds)(cfg)) requirements.add('vectors');
258
+ return requirements;
259
+ }
260
+ function validateRequirements(cfg, entry, requirements) {
261
+ if (requirements.has('vectors') && (0, _indexts.anyPresetEmbeds)(cfg) && !entry.capabilities.has('vectors')) {
262
+ var name = (0, _indexts.storeName)(cfg);
263
+ 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)'));
264
+ }
265
+ }
266
+ function openStoreFor(cfg, options) {
198
267
  return _async_to_generator(function() {
199
- var name, entry;
268
+ var _options_requirements, entry;
200
269
  return _ts_generator(this, function(_state) {
201
- name = (0, _indexts.storeName)(cfg);
202
- entry = entryFor(name);
203
- // The one unambiguous, config-level capability need: an embed block some preset actually uses
204
- // 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.
205
- if ((0, _indexts.anyPresetEmbeds)(cfg) && !entry.capabilities.has('vectors')) {
206
- 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)'));
207
- }
270
+ entry = entryFor((0, _indexts.storeName)(cfg));
271
+ validateRequirements(cfg, entry, (_options_requirements = options.requirements) !== null && _options_requirements !== void 0 ? _options_requirements : new Set([
272
+ 'core'
273
+ ]));
208
274
  return [
209
275
  2,
210
- entry.open(cfg)
276
+ entry.open(cfg, options)
211
277
  ];
212
278
  });
213
279
  })();
214
280
  }
281
+ function openStore(_0) {
282
+ return _async_to_generator(function(cfg) {
283
+ var options, buildEnabled;
284
+ var _arguments = arguments;
285
+ return _ts_generator(this, function(_state) {
286
+ options = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : {};
287
+ buildEnabled = options.build !== false;
288
+ return [
289
+ 2,
290
+ openStoreFor(cfg, {
291
+ build: buildEnabled,
292
+ requirements: buildEnabled ? requirementsFor(cfg) : new Set([
293
+ 'core'
294
+ ])
295
+ })
296
+ ];
297
+ });
298
+ }).apply(this, arguments);
299
+ }
300
+ function lexicalReadiness(cfg) {
301
+ return _async_to_generator(function() {
302
+ var opened, err;
303
+ return _ts_generator(this, function(_state) {
304
+ switch(_state.label){
305
+ case 0:
306
+ _state.trys.push([
307
+ 0,
308
+ 2,
309
+ ,
310
+ 3
311
+ ]);
312
+ return [
313
+ 4,
314
+ openStoreFor(cfg, {
315
+ build: false,
316
+ requirements: new Set([
317
+ 'core',
318
+ 'lexical'
319
+ ])
320
+ })
321
+ ];
322
+ case 1:
323
+ opened = _state.sent();
324
+ return [
325
+ 3,
326
+ 3
327
+ ];
328
+ case 2:
329
+ err = _state.sent();
330
+ if (_instanceof(err, _errorsts.SenseError) && err.code === 'INDEX_NOT_READY') return [
331
+ 2,
332
+ {
333
+ ready: false,
334
+ error: err.message
335
+ }
336
+ ];
337
+ throw err;
338
+ case 3:
339
+ _state.trys.push([
340
+ 3,
341
+ ,
342
+ 4,
343
+ 6
344
+ ]);
345
+ return [
346
+ 2,
347
+ {
348
+ ready: true,
349
+ error: null
350
+ }
351
+ ];
352
+ case 4:
353
+ return [
354
+ 4,
355
+ opened.store.close()
356
+ ];
357
+ case 5:
358
+ _state.sent();
359
+ return [
360
+ 7
361
+ ];
362
+ case 6:
363
+ return [
364
+ 2
365
+ ];
366
+ }
367
+ });
368
+ })();
369
+ }
370
+ function buildIndex(_0) {
371
+ return _async_to_generator(function(cfg) {
372
+ var options, opened, _store, result;
373
+ var _arguments = arguments;
374
+ return _ts_generator(this, function(_state) {
375
+ switch(_state.label){
376
+ case 0:
377
+ options = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : {};
378
+ if (options.force) (0, _cachets.clearCache)(cfg);
379
+ return [
380
+ 4,
381
+ openStoreFor(cfg, {
382
+ build: true,
383
+ requirements: requirementsFor(cfg)
384
+ })
385
+ ];
386
+ case 1:
387
+ opened = _state.sent();
388
+ _state.label = 2;
389
+ case 2:
390
+ _state.trys.push([
391
+ 2,
392
+ ,
393
+ 3,
394
+ 5
395
+ ]);
396
+ _store = opened.store, result = _object_without_properties(opened, [
397
+ "store"
398
+ ]);
399
+ return [
400
+ 2,
401
+ result
402
+ ];
403
+ case 3:
404
+ return [
405
+ 4,
406
+ opened.store.close()
407
+ ];
408
+ case 4:
409
+ _state.sent();
410
+ return [
411
+ 7
412
+ ];
413
+ case 5:
414
+ return [
415
+ 2
416
+ ];
417
+ }
418
+ });
419
+ }).apply(this, arguments);
420
+ }
421
+ function storeFilename(cfg) {
422
+ return entryFor((0, _indexts.storeName)(cfg)).filename;
423
+ }
215
424
  /* 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 { 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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/index.ts"],"sourcesContent":["// Rows -> a backing store: registry + the public open/build boundary. Parsing lives in scan.ts;\n// everything 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 { clearCache } from './cache.ts';\nimport { DB_FILENAME as DUCKDB_FILENAME, openDuckdb } from './duckdb/open.ts';\nimport { CAPABILITIES as DUCKDB_CAPABILITIES } from './duckdb/store.ts';\nimport type { BuildRequirement, InternalOpenOptions, OpenOptions, OpenResult } from './open.ts';\nimport { openSqlite, DB_FILENAME as SQLITE_FILENAME } from './sqlite/open.ts';\nimport { CAPABILITIES as SQLITE_CAPABILITIES } from './sqlite/store.ts';\nimport type { Stages } from './stages.ts';\nimport { openTurso, DB_FILENAME as TURSO_FILENAME } 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 filename: string;\n open: (cfg: ResolvedConfig, options?: InternalOpenOptions) => Promise<OpenResult>;\n}\n\nconst REGISTRY: Record<StoreName, StoreEntry> = {\n sqlite: { capabilities: SQLITE_CAPABILITIES, filename: SQLITE_FILENAME, open: openSqlite },\n duckdb: { capabilities: DUCKDB_CAPABILITIES, filename: DUCKDB_FILENAME, open: openDuckdb },\n turso: { capabilities: TURSO_CAPABILITIES, filename: TURSO_FILENAME, 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\nfunction requirementsFor(cfg: ResolvedConfig): Set<BuildRequirement> {\n const requirements = new Set<BuildRequirement>(['core', 'lexical']);\n if (anyPresetEmbeds(cfg)) requirements.add('vectors');\n return requirements;\n}\n\nfunction validateRequirements(cfg: ResolvedConfig, entry: StoreEntry, requirements: ReadonlySet<BuildRequirement>): void {\n if (requirements.has('vectors') && anyPresetEmbeds(cfg) && !entry.capabilities.has('vectors')) {\n const name = storeName(cfg);\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\nexport async function openStoreFor(cfg: ResolvedConfig, options: InternalOpenOptions): Promise<OpenResult> {\n const entry = entryFor(storeName(cfg));\n validateRequirements(cfg, entry, options.requirements ?? new Set<BuildRequirement>(['core']));\n return entry.open(cfg, options);\n}\n\nexport async function openStore(cfg: ResolvedConfig, options: OpenOptions = {}): Promise<OpenResult> {\n const buildEnabled = options.build !== false;\n return openStoreFor(cfg, {\n build: buildEnabled,\n requirements: buildEnabled ? requirementsFor(cfg) : new Set<BuildRequirement>(['core']),\n });\n}\n\nexport async function lexicalReadiness(cfg: ResolvedConfig): Promise<{ ready: boolean; error: string | null }> {\n let opened: OpenResult;\n try {\n opened = await openStoreFor(cfg, { build: false, requirements: new Set<BuildRequirement>(['core', 'lexical']) });\n } catch (err) {\n if (err instanceof SenseError && err.code === 'INDEX_NOT_READY') return { ready: false, error: err.message };\n throw err;\n }\n try {\n return { ready: true, error: null };\n } finally {\n await opened.store.close();\n }\n}\n\nexport interface BuildOptions {\n force?: boolean;\n}\n\nexport interface BuildResult {\n cfg: ResolvedConfig;\n dbPath: string;\n parsed: number;\n warnings: string[];\n stages: Stages;\n}\n\nexport async function buildIndex(cfg: ResolvedConfig, options: BuildOptions = {}): Promise<BuildResult> {\n if (options.force) clearCache(cfg);\n const opened = await openStoreFor(cfg, { build: true, requirements: requirementsFor(cfg) });\n try {\n const { store: _store, ...result } = opened;\n return result;\n } finally {\n await opened.store.close();\n }\n}\n\nexport function storeFilename(cfg: ResolvedConfig): string {\n return entryFor(storeName(cfg)).filename;\n}\n\nexport type { OpenOptions, 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';\nexport { clearCache };\n"],"names":["CAPABILITY_NAMES","DB_FILENAME","SCHEMA_VERSION","buildIndex","clearCache","docCount","getMeta","lexicalReadiness","openStore","openStoreFor","setMeta","storeFilename","REGISTRY","sqlite","capabilities","SQLITE_CAPABILITIES","filename","SQLITE_FILENAME","open","openSqlite","duckdb","DUCKDB_CAPABILITIES","DUCKDB_FILENAME","openDuckdb","turso","TURSO_CAPABILITIES","TURSO_FILENAME","openTurso","entryFor","name","entry","SenseError","Object","keys","join","requirementsFor","cfg","requirements","Set","anyPresetEmbeds","add","validateRequirements","has","storeName","options","buildEnabled","build","opened","err","code","ready","error","message","store","close","_store","result","force"],"mappings":"AAAA,gGAAgG;AAChG,kEAAkE;;;;;;;;;;;;QA6GzDA;eAAAA,yBAAgB;;QAHhBC;eAAAA,oBAAW;;QAAEC;eAAAA,uBAAc;;QAlBdC;eAAAA;;QAsBbC;eAAAA,mBAAU;;QANVC;eAAAA,iBAAQ;;QACRC;eAAAA,iBAAO;;QA5CMC;eAAAA;;QARAC;eAAAA;;QANAC;eAAAA;;QA0DJC;eAAAA,iBAAO;;QANTC;eAAAA;;;uBAhG2B;wBAChB;uBACA;sBACgC;uBACP;uBAEO;wBACP;uBAEK;wBACN;uBA2F1B;wBACQ;uBAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAvFjC,IAAMC,WAA0C;IAC9CC,QAAQ;QAAEC,cAAcC,sBAAmB;QAAEC,UAAUC,oBAAe;QAAEC,MAAMC,mBAAU;IAAC;IACzFC,QAAQ;QAAEN,cAAcO,qBAAmB;QAAEL,UAAUM,mBAAe;QAAEJ,MAAMK,kBAAU;IAAC;IACzFC,OAAO;QAAEV,cAAcW,sBAAkB;QAAET,UAAUU,oBAAc;QAAER,MAAMS,kBAAS;IAAC;AACvF;AAEA,SAASC,SAASC,IAAe;IAC/B,IAAMC,QAAQlB,QAAQ,CAACiB,KAAK;IAC5B,IAAI,CAACC,OAAO,MAAM,IAAIC,oBAAU,CAAC,iBAAiB,AAAC,0BAA8CC,OAArBH,MAAK,kBAAiD,OAAjCG,OAAOC,IAAI,CAACrB,UAAUsB,IAAI,CAAC;IAC5H,OAAOJ;AACT;AAEA,SAASK,gBAAgBC,GAAmB;IAC1C,IAAMC,eAAe,IAAIC,IAAsB;QAAC;QAAQ;KAAU;IAClE,IAAIC,IAAAA,wBAAe,EAACH,MAAMC,aAAaG,GAAG,CAAC;IAC3C,OAAOH;AACT;AAEA,SAASI,qBAAqBL,GAAmB,EAAEN,KAAiB,EAAEO,YAA2C;IAC/G,IAAIA,aAAaK,GAAG,CAAC,cAAcH,IAAAA,wBAAe,EAACH,QAAQ,CAACN,MAAMhB,YAAY,CAAC4B,GAAG,CAAC,YAAY;QAC7F,IAAMb,OAAOc,IAAAA,kBAAS,EAACP;QACvB,MAAM,IAAIL,oBAAU,CAAC,4BAA4B,AAAC,UAAc,OAALF,MAAK;IAClE;AACF;AAEO,SAAepB,aAAa2B,GAAmB,EAAEQ,OAA4B;;YAEjDA,uBAD3Bd;;YAAAA,QAAQF,SAASe,IAAAA,kBAAS,EAACP;YACjCK,qBAAqBL,KAAKN,QAAOc,wBAAAA,QAAQP,YAAY,cAApBO,mCAAAA,wBAAwB,IAAIN;gBAAuB;;YACpF;;gBAAOR,MAAMZ,IAAI,CAACkB,KAAKQ;;;IACzB;;AAEO,SAAepC;wCAAU4B,GAAmB;YAAEQ,SAC7CC;;;YAD6CD,UAAAA,oEAAuB,CAAC;YACrEC,eAAeD,QAAQE,KAAK,KAAK;YACvC;;gBAAOrC,aAAa2B,KAAK;oBACvBU,OAAOD;oBACPR,cAAcQ,eAAeV,gBAAgBC,OAAO,IAAIE;wBAAuB;;gBACjF;;;IACF;;AAEO,SAAe/B,iBAAiB6B,GAAmB;;YACpDW,QAGKC;;;;;;;;;;oBADE;;wBAAMvC,aAAa2B,KAAK;4BAAEU,OAAO;4BAAOT,cAAc,IAAIC;gCAAuB;gCAAQ;;wBAAY;;;oBAA9GS,SAAS;;;;;;oBACFC;oBACP,IAAIA,AAAG,YAAHA,KAAejB,oBAAU,KAAIiB,IAAIC,IAAI,KAAK,mBAAmB;;wBAAO;4BAAEC,OAAO;4BAAOC,OAAOH,IAAII,OAAO;wBAAC;;oBAC3G,MAAMJ;;;;;;;;oBAGN;;wBAAO;4BAAEE,OAAO;4BAAMC,OAAO;wBAAK;;;oBAElC;;wBAAMJ,OAAOM,KAAK,CAACC,KAAK;;;oBAAxB;;;;;;;;;;IAEJ;;AAcO,SAAenD;wCAAWiC,GAAmB;YAAEQ,SAE9CG,QAEWQ,QAAWC;;;;;oBAJwBZ,UAAAA,oEAAwB,CAAC;oBAC7E,IAAIA,QAAQa,KAAK,EAAErD,IAAAA,mBAAU,EAACgC;oBACf;;wBAAM3B,aAAa2B,KAAK;4BAAEU,OAAO;4BAAMT,cAAcF,gBAAgBC;wBAAK;;;oBAAnFW,SAAS;;;;;;;;;oBAEEQ,SAAsBR,OAA7BM,OAAkBG,oCAAWT;;;oBACrC;;wBAAOS;;;oBAEP;;wBAAMT,OAAOM,KAAK,CAACC,KAAK;;;oBAAxB;;;;;;;;;;IAEJ;;AAEO,SAAS3C,cAAcyB,GAAmB;IAC/C,OAAOR,SAASe,IAAAA,kBAAS,EAACP,MAAMpB,QAAQ;AAC1C"}