sensemaking 0.18.4 → 0.19.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 (368) hide show
  1. package/README.md +22 -4
  2. package/dist/cjs/chunk/group.js +10 -23
  3. package/dist/cjs/chunk/group.js.map +1 -1
  4. package/dist/cjs/chunk/parse.js +2 -5
  5. package/dist/cjs/chunk/parse.js.map +1 -1
  6. package/dist/cjs/cli/index.js.map +1 -1
  7. package/dist/cjs/cli/shared.js +6 -10
  8. package/dist/cjs/cli/shared.js.map +1 -1
  9. package/dist/cjs/cli/status.js +44 -10
  10. package/dist/cjs/cli/status.js.map +1 -1
  11. package/dist/cjs/cli.js +2 -8
  12. package/dist/cjs/cli.js.map +1 -1
  13. package/dist/cjs/commands/map.js +1 -3
  14. package/dist/cjs/commands/map.js.map +1 -1
  15. package/dist/cjs/commands/peek.js.map +1 -1
  16. package/dist/cjs/commands/related.js +3 -5
  17. package/dist/cjs/commands/related.js.map +1 -1
  18. package/dist/cjs/commands/scope.js.map +1 -1
  19. package/dist/cjs/commands/search.js +6 -8
  20. package/dist/cjs/commands/search.js.map +1 -1
  21. package/dist/cjs/commands/signals.js.map +1 -1
  22. package/dist/cjs/config/access.js.map +1 -1
  23. package/dist/cjs/config/index.d.cts +1 -1
  24. package/dist/cjs/config/index.d.ts +1 -1
  25. package/dist/cjs/config/index.js +3 -0
  26. package/dist/cjs/config/index.js.map +1 -1
  27. package/dist/cjs/config/load.js +10 -24
  28. package/dist/cjs/config/load.js.map +1 -1
  29. package/dist/cjs/config/resolve.js.map +1 -1
  30. package/dist/cjs/config/signals.js +2 -3
  31. package/dist/cjs/config/signals.js.map +1 -1
  32. package/dist/cjs/config/types.d.cts +2 -1
  33. package/dist/cjs/config/types.d.ts +2 -1
  34. package/dist/cjs/config/types.js +8 -0
  35. package/dist/cjs/config/types.js.map +1 -1
  36. package/dist/cjs/config/validate.d.cts +1 -1
  37. package/dist/cjs/config/validate.d.ts +1 -1
  38. package/dist/cjs/config/validate.js +9 -10
  39. package/dist/cjs/config/validate.js.map +1 -1
  40. package/dist/cjs/embed/cohere.js +2 -2
  41. package/dist/cjs/embed/cohere.js.map +1 -1
  42. package/dist/cjs/embed/distribution.js +3 -3
  43. package/dist/cjs/embed/distribution.js.map +1 -1
  44. package/dist/cjs/embed/handoff.d.cts +3 -0
  45. package/dist/cjs/embed/handoff.d.ts +3 -0
  46. package/dist/cjs/embed/handoff.js +39 -0
  47. package/dist/cjs/embed/handoff.js.map +1 -0
  48. package/dist/cjs/embed/identity.d.cts +11 -10
  49. package/dist/cjs/embed/identity.d.ts +11 -10
  50. package/dist/cjs/embed/identity.js +30 -15
  51. package/dist/cjs/embed/identity.js.map +1 -1
  52. package/dist/cjs/embed/langfit.js +2 -3
  53. package/dist/cjs/embed/langfit.js.map +1 -1
  54. package/dist/cjs/embed/languages.js +2 -4
  55. package/dist/cjs/embed/languages.js.map +1 -1
  56. package/dist/cjs/embed/openai.js +2 -2
  57. package/dist/cjs/embed/openai.js.map +1 -1
  58. package/dist/cjs/embed/query.js +58 -20
  59. package/dist/cjs/embed/query.js.map +1 -1
  60. package/dist/cjs/embed/registry.js +1 -2
  61. package/dist/cjs/embed/registry.js.map +1 -1
  62. package/dist/cjs/embed/static.d.cts +1 -1
  63. package/dist/cjs/embed/static.d.ts +1 -1
  64. package/dist/cjs/embed/static.js +8 -10
  65. package/dist/cjs/embed/static.js.map +1 -1
  66. package/dist/cjs/embed/store.d.cts +2 -2
  67. package/dist/cjs/embed/store.d.ts +2 -2
  68. package/dist/cjs/embed/store.js +48 -34
  69. package/dist/cjs/embed/store.js.map +1 -1
  70. package/dist/cjs/embed/types.js +1 -3
  71. package/dist/cjs/embed/types.js.map +1 -1
  72. package/dist/cjs/errors.d.cts +1 -1
  73. package/dist/cjs/errors.d.ts +1 -1
  74. package/dist/cjs/errors.js.map +1 -1
  75. package/dist/cjs/features/embed.js +19 -17
  76. package/dist/cjs/features/embed.js.map +1 -1
  77. package/dist/cjs/features/fences.js +5 -10
  78. package/dist/cjs/features/fences.js.map +1 -1
  79. package/dist/cjs/features/links.js +20 -37
  80. package/dist/cjs/features/links.js.map +1 -1
  81. package/dist/cjs/features/sections.js +21 -19
  82. package/dist/cjs/features/sections.js.map +1 -1
  83. package/dist/cjs/features/tags.js +5 -8
  84. package/dist/cjs/features/tags.js.map +1 -1
  85. package/dist/cjs/graph/traverse.js +1 -2
  86. package/dist/cjs/graph/traverse.js.map +1 -1
  87. package/dist/cjs/index.d.cts +1 -1
  88. package/dist/cjs/index.d.ts +1 -1
  89. package/dist/cjs/index.js +3 -0
  90. package/dist/cjs/index.js.map +1 -1
  91. package/dist/cjs/output/column-hint.js +3 -6
  92. package/dist/cjs/output/column-hint.js.map +1 -1
  93. package/dist/cjs/output/output.js +7 -14
  94. package/dist/cjs/output/output.js.map +1 -1
  95. package/dist/cjs/output/search-error.js +2 -5
  96. package/dist/cjs/output/search-error.js.map +1 -1
  97. package/dist/cjs/scan/frontmatter.d.cts +1 -0
  98. package/dist/cjs/scan/frontmatter.d.ts +1 -0
  99. package/dist/cjs/scan/frontmatter.js +14 -18
  100. package/dist/cjs/scan/frontmatter.js.map +1 -1
  101. package/dist/cjs/scan/list.js +2 -3
  102. package/dist/cjs/scan/list.js.map +1 -1
  103. package/dist/cjs/scan/reparse.js +12 -26
  104. package/dist/cjs/scan/reparse.js.map +1 -1
  105. package/dist/cjs/scan/worker-error.js.map +1 -1
  106. package/dist/cjs/store/cache.d.cts +2 -0
  107. package/dist/cjs/store/cache.d.ts +2 -0
  108. package/dist/cjs/store/cache.js +20 -0
  109. package/dist/cjs/store/cache.js.map +1 -0
  110. package/dist/cjs/store/duckdb/batch.js +4 -16
  111. package/dist/cjs/store/duckdb/batch.js.map +1 -1
  112. package/dist/cjs/store/duckdb/connection.js +8 -20
  113. package/dist/cjs/store/duckdb/connection.js.map +1 -1
  114. package/dist/cjs/store/duckdb/fieldStats.js +2 -8
  115. package/dist/cjs/store/duckdb/fieldStats.js.map +1 -1
  116. package/dist/cjs/store/duckdb/lexical.js +14 -28
  117. package/dist/cjs/store/duckdb/lexical.js.map +1 -1
  118. package/dist/cjs/store/duckdb/native.js.map +1 -1
  119. package/dist/cjs/store/duckdb/open.js +12 -13
  120. package/dist/cjs/store/duckdb/open.js.map +1 -1
  121. package/dist/cjs/store/duckdb/reconcile.js +4 -11
  122. package/dist/cjs/store/duckdb/reconcile.js.map +1 -1
  123. package/dist/cjs/store/duckdb/sql-functions.js +2 -4
  124. package/dist/cjs/store/duckdb/sql-functions.js.map +1 -1
  125. package/dist/cjs/store/duckdb/store.js +2 -3
  126. package/dist/cjs/store/duckdb/store.js.map +1 -1
  127. package/dist/cjs/store/duckdb/vectors.js +8 -18
  128. package/dist/cjs/store/duckdb/vectors.js.map +1 -1
  129. package/dist/cjs/store/index.d.cts +3 -2
  130. package/dist/cjs/store/index.d.ts +3 -2
  131. package/dist/cjs/store/index.js +7 -8
  132. package/dist/cjs/store/index.js.map +1 -1
  133. package/dist/cjs/store/native.js +6 -16
  134. package/dist/cjs/store/native.js.map +1 -1
  135. package/dist/cjs/store/sql-functions.js.map +1 -1
  136. package/dist/cjs/store/sqlite/connection.js +4 -8
  137. package/dist/cjs/store/sqlite/connection.js.map +1 -1
  138. package/dist/cjs/store/sqlite/fieldStats.js.map +1 -1
  139. package/dist/cjs/store/sqlite/lexical.js +3 -5
  140. package/dist/cjs/store/sqlite/lexical.js.map +1 -1
  141. package/dist/cjs/store/sqlite/open.d.cts +0 -1
  142. package/dist/cjs/store/sqlite/open.d.ts +0 -1
  143. package/dist/cjs/store/sqlite/open.js +22 -40
  144. package/dist/cjs/store/sqlite/open.js.map +1 -1
  145. package/dist/cjs/store/sqlite/reconcile.js +2 -3
  146. package/dist/cjs/store/sqlite/reconcile.js.map +1 -1
  147. package/dist/cjs/store/sqlite/sql-functions.js +2 -4
  148. package/dist/cjs/store/sqlite/sql-functions.js.map +1 -1
  149. package/dist/cjs/store/sqlite/store.js.map +1 -1
  150. package/dist/cjs/store/transaction.js +1 -3
  151. package/dist/cjs/store/transaction.js.map +1 -1
  152. package/dist/cjs/store/turso/connection.js +2 -6
  153. package/dist/cjs/store/turso/connection.js.map +1 -1
  154. package/dist/cjs/store/turso/fieldStats.js.map +1 -1
  155. package/dist/cjs/store/turso/lexical.d.cts +2 -0
  156. package/dist/cjs/store/turso/lexical.d.ts +2 -0
  157. package/dist/cjs/store/turso/lexical.js +347 -0
  158. package/dist/cjs/store/turso/lexical.js.map +1 -0
  159. package/dist/cjs/store/turso/native.js.map +1 -1
  160. package/dist/cjs/store/turso/open.d.cts +1 -1
  161. package/dist/cjs/store/turso/open.d.ts +1 -1
  162. package/dist/cjs/store/turso/open.js +81 -54
  163. package/dist/cjs/store/turso/open.js.map +1 -1
  164. package/dist/cjs/store/turso/reconcile.js +22 -22
  165. package/dist/cjs/store/turso/reconcile.js.map +1 -1
  166. package/dist/cjs/store/turso/store.js +18 -41
  167. package/dist/cjs/store/turso/store.js.map +1 -1
  168. package/dist/cjs/store/turso/vectors.d.cts +8 -0
  169. package/dist/cjs/store/turso/vectors.d.ts +8 -0
  170. package/dist/cjs/store/turso/vectors.js +435 -0
  171. package/dist/cjs/store/turso/vectors.js.map +1 -0
  172. package/dist/cjs/store/types.js +2 -3
  173. package/dist/cjs/store/types.js.map +1 -1
  174. package/dist/cjs/store/vectors.js.map +1 -1
  175. package/dist/cjs/text/segment.d.cts +1 -0
  176. package/dist/cjs/text/segment.d.ts +1 -0
  177. package/dist/cjs/text/segment.js +10 -14
  178. package/dist/cjs/text/segment.js.map +1 -1
  179. package/dist/cjs/watch.js +2 -5
  180. package/dist/cjs/watch.js.map +1 -1
  181. package/dist/cjs/workers/parse.js.map +1 -1
  182. package/dist/esm/chunk/group.js +10 -23
  183. package/dist/esm/chunk/group.js.map +1 -1
  184. package/dist/esm/chunk/parse.js +4 -8
  185. package/dist/esm/chunk/parse.js.map +1 -1
  186. package/dist/esm/cli/index.js +3 -5
  187. package/dist/esm/cli/index.js.map +1 -1
  188. package/dist/esm/cli/shared.js +12 -22
  189. package/dist/esm/cli/shared.js.map +1 -1
  190. package/dist/esm/cli/status.js +43 -9
  191. package/dist/esm/cli/status.js.map +1 -1
  192. package/dist/esm/cli.js +2 -8
  193. package/dist/esm/cli.js.map +1 -1
  194. package/dist/esm/commands/map.js +1 -3
  195. package/dist/esm/commands/map.js.map +1 -1
  196. package/dist/esm/commands/peek.js.map +1 -1
  197. package/dist/esm/commands/related.js +3 -5
  198. package/dist/esm/commands/related.js.map +1 -1
  199. package/dist/esm/commands/scope.js +3 -5
  200. package/dist/esm/commands/scope.js.map +1 -1
  201. package/dist/esm/commands/search.js +10 -16
  202. package/dist/esm/commands/search.js.map +1 -1
  203. package/dist/esm/commands/signals.js +3 -7
  204. package/dist/esm/commands/signals.js.map +1 -1
  205. package/dist/esm/config/access.js +8 -13
  206. package/dist/esm/config/access.js.map +1 -1
  207. package/dist/esm/config/index.d.ts +1 -1
  208. package/dist/esm/config/index.js +1 -1
  209. package/dist/esm/config/index.js.map +1 -1
  210. package/dist/esm/config/load.js +10 -24
  211. package/dist/esm/config/load.js.map +1 -1
  212. package/dist/esm/config/resolve.js +2 -3
  213. package/dist/esm/config/resolve.js.map +1 -1
  214. package/dist/esm/config/signals.js +3 -5
  215. package/dist/esm/config/signals.js.map +1 -1
  216. package/dist/esm/config/types.d.ts +2 -1
  217. package/dist/esm/config/types.js +8 -2
  218. package/dist/esm/config/types.js.map +1 -1
  219. package/dist/esm/config/validate.d.ts +1 -1
  220. package/dist/esm/config/validate.js +7 -10
  221. package/dist/esm/config/validate.js.map +1 -1
  222. package/dist/esm/embed/cohere.js +2 -2
  223. package/dist/esm/embed/cohere.js.map +1 -1
  224. package/dist/esm/embed/distribution.js +1 -1
  225. package/dist/esm/embed/distribution.js.map +1 -1
  226. package/dist/esm/embed/handoff.d.ts +3 -0
  227. package/dist/esm/embed/handoff.js +21 -0
  228. package/dist/esm/embed/handoff.js.map +1 -0
  229. package/dist/esm/embed/identity.d.ts +11 -10
  230. package/dist/esm/embed/identity.js +29 -26
  231. package/dist/esm/embed/identity.js.map +1 -1
  232. package/dist/esm/embed/langfit.js +2 -3
  233. package/dist/esm/embed/langfit.js.map +1 -1
  234. package/dist/esm/embed/languages.js +2 -4
  235. package/dist/esm/embed/languages.js.map +1 -1
  236. package/dist/esm/embed/openai.js +2 -2
  237. package/dist/esm/embed/openai.js.map +1 -1
  238. package/dist/esm/embed/query.js +21 -6
  239. package/dist/esm/embed/query.js.map +1 -1
  240. package/dist/esm/embed/registry.js +1 -2
  241. package/dist/esm/embed/registry.js.map +1 -1
  242. package/dist/esm/embed/static.d.ts +1 -1
  243. package/dist/esm/embed/static.js +8 -10
  244. package/dist/esm/embed/static.js.map +1 -1
  245. package/dist/esm/embed/store.d.ts +2 -2
  246. package/dist/esm/embed/store.js +28 -23
  247. package/dist/esm/embed/store.js.map +1 -1
  248. package/dist/esm/embed/types.js +1 -3
  249. package/dist/esm/embed/types.js.map +1 -1
  250. package/dist/esm/errors.d.ts +1 -1
  251. package/dist/esm/errors.js.map +1 -1
  252. package/dist/esm/features/embed.js +16 -16
  253. package/dist/esm/features/embed.js.map +1 -1
  254. package/dist/esm/features/fences.js +9 -19
  255. package/dist/esm/features/fences.js.map +1 -1
  256. package/dist/esm/features/links.js +24 -49
  257. package/dist/esm/features/links.js.map +1 -1
  258. package/dist/esm/features/sections.js +20 -20
  259. package/dist/esm/features/sections.js.map +1 -1
  260. package/dist/esm/features/tags.js +5 -8
  261. package/dist/esm/features/tags.js.map +1 -1
  262. package/dist/esm/features/types.js.map +1 -1
  263. package/dist/esm/graph/traverse.js +1 -2
  264. package/dist/esm/graph/traverse.js.map +1 -1
  265. package/dist/esm/index.d.ts +1 -1
  266. package/dist/esm/index.js +1 -1
  267. package/dist/esm/index.js.map +1 -1
  268. package/dist/esm/output/column-hint.js +3 -6
  269. package/dist/esm/output/column-hint.js.map +1 -1
  270. package/dist/esm/output/output.js +9 -20
  271. package/dist/esm/output/output.js.map +1 -1
  272. package/dist/esm/output/search-error.js +2 -5
  273. package/dist/esm/output/search-error.js.map +1 -1
  274. package/dist/esm/scan/frontmatter.d.ts +1 -0
  275. package/dist/esm/scan/frontmatter.js +13 -18
  276. package/dist/esm/scan/frontmatter.js.map +1 -1
  277. package/dist/esm/scan/list.js +2 -3
  278. package/dist/esm/scan/list.js.map +1 -1
  279. package/dist/esm/scan/reparse.js +16 -34
  280. package/dist/esm/scan/reparse.js.map +1 -1
  281. package/dist/esm/scan/worker-error.js.map +1 -1
  282. package/dist/esm/store/cache.d.ts +2 -0
  283. package/dist/esm/store/cache.js +11 -0
  284. package/dist/esm/store/cache.js.map +1 -0
  285. package/dist/esm/store/duckdb/batch.js +4 -16
  286. package/dist/esm/store/duckdb/batch.js.map +1 -1
  287. package/dist/esm/store/duckdb/connection.js +8 -20
  288. package/dist/esm/store/duckdb/connection.js.map +1 -1
  289. package/dist/esm/store/duckdb/fieldStats.js +4 -12
  290. package/dist/esm/store/duckdb/fieldStats.js.map +1 -1
  291. package/dist/esm/store/duckdb/lexical.js +19 -35
  292. package/dist/esm/store/duckdb/lexical.js.map +1 -1
  293. package/dist/esm/store/duckdb/native.js +2 -7
  294. package/dist/esm/store/duckdb/native.js.map +1 -1
  295. package/dist/esm/store/duckdb/open.js +16 -23
  296. package/dist/esm/store/duckdb/open.js.map +1 -1
  297. package/dist/esm/store/duckdb/reconcile.js +4 -11
  298. package/dist/esm/store/duckdb/reconcile.js.map +1 -1
  299. package/dist/esm/store/duckdb/sql-functions.js +4 -9
  300. package/dist/esm/store/duckdb/sql-functions.js.map +1 -1
  301. package/dist/esm/store/duckdb/store.js +6 -14
  302. package/dist/esm/store/duckdb/store.js.map +1 -1
  303. package/dist/esm/store/duckdb/vectors.js +14 -31
  304. package/dist/esm/store/duckdb/vectors.js.map +1 -1
  305. package/dist/esm/store/index.d.ts +3 -2
  306. package/dist/esm/store/index.js +5 -6
  307. package/dist/esm/store/index.js.map +1 -1
  308. package/dist/esm/store/native.js +10 -25
  309. package/dist/esm/store/native.js.map +1 -1
  310. package/dist/esm/store/sql-functions.js +3 -5
  311. package/dist/esm/store/sql-functions.js.map +1 -1
  312. package/dist/esm/store/sqlite/connection.js +4 -8
  313. package/dist/esm/store/sqlite/connection.js.map +1 -1
  314. package/dist/esm/store/sqlite/fieldStats.js +2 -6
  315. package/dist/esm/store/sqlite/fieldStats.js.map +1 -1
  316. package/dist/esm/store/sqlite/lexical.js +5 -9
  317. package/dist/esm/store/sqlite/lexical.js.map +1 -1
  318. package/dist/esm/store/sqlite/open.d.ts +0 -1
  319. package/dist/esm/store/sqlite/open.js +21 -41
  320. package/dist/esm/store/sqlite/open.js.map +1 -1
  321. package/dist/esm/store/sqlite/reconcile.js +6 -13
  322. package/dist/esm/store/sqlite/reconcile.js.map +1 -1
  323. package/dist/esm/store/sqlite/sql-functions.js +2 -4
  324. package/dist/esm/store/sqlite/sql-functions.js.map +1 -1
  325. package/dist/esm/store/sqlite/store.js +1 -2
  326. package/dist/esm/store/sqlite/store.js.map +1 -1
  327. package/dist/esm/store/transaction.js +2 -5
  328. package/dist/esm/store/transaction.js.map +1 -1
  329. package/dist/esm/store/turso/connection.js +2 -6
  330. package/dist/esm/store/turso/connection.js.map +1 -1
  331. package/dist/esm/store/turso/fieldStats.js +2 -5
  332. package/dist/esm/store/turso/fieldStats.js.map +1 -1
  333. package/dist/esm/store/turso/lexical.d.ts +2 -0
  334. package/dist/esm/store/turso/lexical.js +128 -0
  335. package/dist/esm/store/turso/lexical.js.map +1 -0
  336. package/dist/esm/store/turso/native.js +2 -7
  337. package/dist/esm/store/turso/native.js.map +1 -1
  338. package/dist/esm/store/turso/open.d.ts +1 -1
  339. package/dist/esm/store/turso/open.js +36 -29
  340. package/dist/esm/store/turso/open.js.map +1 -1
  341. package/dist/esm/store/turso/reconcile.js +22 -22
  342. package/dist/esm/store/turso/reconcile.js.map +1 -1
  343. package/dist/esm/store/turso/store.js +17 -28
  344. package/dist/esm/store/turso/store.js.map +1 -1
  345. package/dist/esm/store/turso/vectors.d.ts +8 -0
  346. package/dist/esm/store/turso/vectors.js +98 -0
  347. package/dist/esm/store/turso/vectors.js.map +1 -0
  348. package/dist/esm/store/types.js +2 -3
  349. package/dist/esm/store/types.js.map +1 -1
  350. package/dist/esm/store/vectors.js +2 -3
  351. package/dist/esm/store/vectors.js.map +1 -1
  352. package/dist/esm/text/segment.d.ts +1 -0
  353. package/dist/esm/text/segment.js +13 -21
  354. package/dist/esm/text/segment.js.map +1 -1
  355. package/dist/esm/watch.js +2 -5
  356. package/dist/esm/watch.js.map +1 -1
  357. package/dist/esm/workers/parse.js.map +1 -1
  358. package/package.json +3 -1
  359. package/schema.json +2 -2
  360. package/skills/sense/SKILL.md +2 -2
  361. package/skills/sense-setup/SKILL.md +3 -3
  362. package/dist/cjs/store/meta.d.cts +0 -3
  363. package/dist/cjs/store/meta.d.ts +0 -3
  364. package/dist/cjs/store/meta.js +0 -215
  365. package/dist/cjs/store/meta.js.map +0 -1
  366. package/dist/esm/store/meta.d.ts +0 -3
  367. package/dist/esm/store/meta.js +0 -17
  368. package/dist/esm/store/meta.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/duckdb/reconcile.ts"],"sourcesContent":["import type { Config } from '../../config/index.ts';\nimport { SenseError } from '../../errors.ts';\nimport { activeFeatures } from '../../features/index.ts';\nimport type { ExtractedDoc, ReconcileDelta } from '../../features/types.ts';\nimport { progress } from '../../output/progress.ts';\nimport type { ParsedDoc } from '../../scan/index.ts';\nimport { listFiles, RESERVED_COLUMNS } from '../../scan/index.ts';\nimport { reparseFiles } from '../../scan/reparse.ts';\nimport { getColumns, quoteIdent } from '../shared.ts';\nimport { withTransaction } from '../transaction.ts';\nimport type { Connection } from '../types.ts';\n\n// Mirrors src/store/sqlite/reconcile.ts's frontmatter-upsert shape (dynamic ALTER TABLE per\n// discovered key, ON CONFLICT upsert keeping the row's identity stable). `content` is a plain\n// table, not FTS-virtual (D1: DuckDB's fts index is built lazily, on first lexical query, from\n// this table -- see duckdb/lexical.ts), so its rows are maintained here unconditionally. The one\n// forced divergence for frontmatter itself is the ALTER TABLE type: DuckDB requires a declared\n// column type where sqlite accepts none, so every dynamic frontmatter column is VARIANT (the\n// only DuckDB type that can hold the different JS types mapValue() produces across files for\n// the same key).\nconst CORE_FRONTMATTER_COLUMNS = new Set(['path', '_mtime', '_ctime', '_size', '_parse_error']);\n\n// No rowid coupling needed (unlike sqlite's content, which links to frontmatter's rowid):\n// `path` is content's own primary key, so this is a plain per-doc row.\nconst INSERT_CONTENT_SQL = `INSERT INTO content (\"path\", title, summary, text) VALUES (?, ?, ?, ?)`;\n\nfunction contentRow(doc: ParsedDoc): unknown[] {\n return [doc.relPath, doc.search.title, doc.search.summary, doc.search.text];\n}\n\n// No compile-time column cap in DuckDB (unlike SQLite's SQLITE_MAX_COLUMN); kept as a sanity\n// fence anyway so a runaway frontmatter generator fails with a clear message instead of an\n// unbounded ALTER TABLE loop.\nconst MAX_FRONTMATTER_COLUMNS = 10_000;\n\nexport async function reconcile(conn: Connection, cfg: Config, baseDir: string): Promise<{ parsed: number; warnings: string[] }> {\n const files = listFiles(cfg, baseDir);\n const currentSet = new Set(files.map((f) => f.relPath));\n\n const existingStmt = await conn.prepare('SELECT \"path\", \"_mtime\", \"_size\" FROM frontmatter');\n const existingRows = (await existingStmt.all()) as Array<{ path: string; _mtime: number; _size: number }>;\n const existing = new Map(existingRows.map((r) => [r.path, r]));\n const vanished = existingRows.filter((r) => !currentSet.has(r.path)).map((r) => r.path);\n\n const toReparse = files.filter((f) => {\n const row = existing.get(f.relPath);\n return !row || row._mtime !== f.mtimeMs || row._size !== f.size;\n });\n\n if (vanished.length === 0 && toReparse.length === 0) return { parsed: 0, warnings: [] };\n\n const features = activeFeatures(cfg);\n const seenColumns = await getColumns(conn);\n\n const report = progress('reparsing files', toReparse.length);\n const { docs: parsedDocs, warnings, newColumns } = await reparseFiles(toReparse, features, cfg, seenColumns, report.tick);\n report.finish();\n for (const col of newColumns) seenColumns.add(col);\n\n const allColumns = [...seenColumns];\n if (allColumns.length > MAX_FRONTMATTER_COLUMNS) {\n throw new SenseError('COLUMN_LIMIT', `frontmatter would need ${allColumns.length} columns, crossing this store's sanity limit (${MAX_FRONTMATTER_COLUMNS}). Narrow the presets' include globs so fewer/other files are indexed, or fix whatever is generating unbounded frontmatter keys.`);\n }\n const writableColumns = allColumns.filter((c) => CORE_FRONTMATTER_COLUMNS.has(c) || !RESERVED_COLUMNS.has(c));\n const insertSql = `INSERT INTO frontmatter (${writableColumns.map(quoteIdent).join(', ')}) VALUES (${writableColumns.map(() => '?').join(', ')}) ON CONFLICT(\"path\") DO UPDATE SET ${writableColumns\n .filter((c) => c !== 'path')\n .map((c) => `${quoteIdent(c)} = excluded.${quoteIdent(c)}`)\n .join(', ')}`;\n\n const added = toReparse.filter((f) => !existing.has(f.relPath)).map((f) => f.relPath);\n const delta: ReconcileDelta = { files, reparsed: parsedDocs.map((d) => d.relPath), added, vanished };\n const addedSet = new Set(added);\n const reparsedExisting = parsedDocs.map((d) => d.relPath).filter((p) => !addedSet.has(p));\n\n await withTransaction(conn, async () => {\n // DuckDB's ALTER TABLE ADD COLUMN requires a type; VARIANT is the only one that can hold\n // the mixed bigint/number/string/null shapes mapValue() produces for one key across files.\n for (const col of newColumns) await conn.exec(`ALTER TABLE frontmatter ADD COLUMN ${quoteIdent(col)} VARIANT`);\n\n if (parsedDocs.length > 0) {\n const rows = parsedDocs.map((doc) =>\n writableColumns.map((col) => {\n if (col === 'path') return doc.relPath;\n if (col === '_mtime') return doc.mtimeMs;\n if (col === '_ctime') return doc.ctimeMs;\n if (col === '_size') return doc.size;\n if (col === '_parse_error') return doc.parseError;\n return doc.data[col] ?? null;\n })\n );\n await conn.runBatch(insertSql, rows);\n }\n\n const contentTouched = [...vanished, ...reparsedExisting];\n if (contentTouched.length > 0)\n await conn.runBatch(\n 'DELETE FROM content WHERE \"path\" = ?',\n contentTouched.map((p) => [p])\n );\n if (parsedDocs.length > 0) await conn.runBatch(INSERT_CONTENT_SQL, parsedDocs.map(contentRow));\n\n if (vanished.length > 0)\n await conn.runBatch(\n 'DELETE FROM frontmatter WHERE \"path\" = ?',\n vanished.map((p) => [p])\n );\n\n // A preset edit forces a full rebuild, so an unchanged doc's coverage is already correct;\n // new docs have nothing to clear, which keeps cold builds linear.\n const presetTouched = [...vanished, ...reparsedExisting];\n if (presetTouched.length > 0)\n await conn.runBatch(\n 'DELETE FROM preset_files WHERE \"path\" = ?',\n presetTouched.map((p) => [p])\n );\n const presetRows: unknown[][] = [];\n for (const doc of parsedDocs) for (const presetName of doc.presets) presetRows.push([doc.relPath, presetName]);\n if (presetRows.length > 0) await conn.runBatch('INSERT INTO preset_files (\"path\", preset) VALUES (?, ?)', presetRows);\n\n const removedPaths = [...vanished, ...reparsedExisting];\n if (removedPaths.length > 0) for (const feature of features) await feature.remove?.(conn, removedPaths, delta);\n for (const feature of features) {\n const docsForFeature: ExtractedDoc[] = parsedDocs.map((doc) => ({ path: doc.relPath, extracted: doc.extracted[feature.name] }));\n await feature.store?.(conn, docsForFeature, delta);\n }\n for (const feature of features) await feature.afterReconcile?.(conn, delta);\n });\n\n return { parsed: parsedDocs.length, warnings };\n}\n"],"names":["reconcile","CORE_FRONTMATTER_COLUMNS","Set","INSERT_CONTENT_SQL","contentRow","doc","relPath","search","title","summary","text","MAX_FRONTMATTER_COLUMNS","conn","cfg","baseDir","files","currentSet","existingStmt","existingRows","existing","vanished","toReparse","features","seenColumns","report","parsedDocs","warnings","newColumns","col","allColumns","writableColumns","insertSql","added","delta","addedSet","reparsedExisting","listFiles","map","f","prepare","all","Map","r","path","filter","has","row","get","_mtime","mtimeMs","_size","size","length","parsed","activeFeatures","getColumns","progress","reparseFiles","tick","docs","finish","add","SenseError","c","RESERVED_COLUMNS","quoteIdent","join","reparsed","d","p","withTransaction","feature","rows","contentTouched","presetTouched","presetRows","presetName","removedPaths","exec","ctimeMs","parseError","data","runBatch","presets","push","remove","docsForFeature","extracted","name","store","afterReconcile"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/duckdb/reconcile.ts"],"sourcesContent":["import type { Config } from '../../config/index.ts';\nimport { SenseError } from '../../errors.ts';\nimport { activeFeatures } from '../../features/index.ts';\nimport type { ExtractedDoc, ReconcileDelta } from '../../features/types.ts';\nimport { progress } from '../../output/progress.ts';\nimport type { ParsedDoc } from '../../scan/index.ts';\nimport { listFiles, RESERVED_COLUMNS } from '../../scan/index.ts';\nimport { reparseFiles } from '../../scan/reparse.ts';\nimport { getColumns, quoteIdent } from '../shared.ts';\nimport { withTransaction } from '../transaction.ts';\nimport type { Connection } from '../types.ts';\n\n// Mirrors sqlite/reconcile.ts's frontmatter-upsert shape (dynamic ALTER TABLE per discovered key, ON CONFLICT upsert). `content` is\n// a plain table, not FTS-virtual, so rows are maintained here unconditionally; DuckDB's ALTER TABLE needs a declared type, so every dynamic frontmatter column is VARIANT (holds mapValue()'s mixed JS types for one key across files).\nconst CORE_FRONTMATTER_COLUMNS = new Set(['path', '_mtime', '_ctime', '_size', '_parse_error']);\n\n// No rowid coupling needed (unlike sqlite's content, which links to frontmatter's rowid):\n// `path` is content's own primary key, so this is a plain per-doc row.\nconst INSERT_CONTENT_SQL = `INSERT INTO content (\"path\", title, summary, text) VALUES (?, ?, ?, ?)`;\n\nfunction contentRow(doc: ParsedDoc): unknown[] {\n return [doc.relPath, doc.search.title, doc.search.summary, doc.search.text];\n}\n\n// No compile-time column cap in DuckDB (unlike SQLite's SQLITE_MAX_COLUMN); kept as a sanity fence anyway\n// so a runaway frontmatter generator fails with a clear message instead of an unbounded ALTER TABLE loop.\nconst MAX_FRONTMATTER_COLUMNS = 10_000;\n\nexport async function reconcile(conn: Connection, cfg: Config, baseDir: string): Promise<{ parsed: number; warnings: string[] }> {\n const files = listFiles(cfg, baseDir);\n const currentSet = new Set(files.map((f) => f.relPath));\n\n const existingStmt = await conn.prepare('SELECT \"path\", \"_mtime\", \"_size\" FROM frontmatter');\n const existingRows = (await existingStmt.all()) as Array<{ path: string; _mtime: number; _size: number }>;\n const existing = new Map(existingRows.map((r) => [r.path, r]));\n const vanished = existingRows.filter((r) => !currentSet.has(r.path)).map((r) => r.path);\n\n const toReparse = files.filter((f) => {\n const row = existing.get(f.relPath);\n return !row || row._mtime !== f.mtimeMs || row._size !== f.size;\n });\n\n if (vanished.length === 0 && toReparse.length === 0) return { parsed: 0, warnings: [] };\n\n const features = activeFeatures(cfg);\n const seenColumns = await getColumns(conn);\n\n const report = progress('reparsing files', toReparse.length);\n const { docs: parsedDocs, warnings, newColumns } = await reparseFiles(toReparse, features, cfg, seenColumns, report.tick);\n report.finish();\n for (const col of newColumns) seenColumns.add(col);\n\n const allColumns = [...seenColumns];\n if (allColumns.length > MAX_FRONTMATTER_COLUMNS) {\n throw new SenseError('COLUMN_LIMIT', `frontmatter would need ${allColumns.length} columns, crossing this store's sanity limit (${MAX_FRONTMATTER_COLUMNS}). Narrow the presets' include globs so fewer/other files are indexed, or fix whatever is generating unbounded frontmatter keys.`);\n }\n const writableColumns = allColumns.filter((c) => CORE_FRONTMATTER_COLUMNS.has(c) || !RESERVED_COLUMNS.has(c));\n const insertSql = `INSERT INTO frontmatter (${writableColumns.map(quoteIdent).join(', ')}) VALUES (${writableColumns.map(() => '?').join(', ')}) ON CONFLICT(\"path\") DO UPDATE SET ${writableColumns\n .filter((c) => c !== 'path')\n .map((c) => `${quoteIdent(c)} = excluded.${quoteIdent(c)}`)\n .join(', ')}`;\n\n const added = toReparse.filter((f) => !existing.has(f.relPath)).map((f) => f.relPath);\n const delta: ReconcileDelta = { files, reparsed: parsedDocs.map((d) => d.relPath), added, vanished };\n const addedSet = new Set(added);\n const reparsedExisting = parsedDocs.map((d) => d.relPath).filter((p) => !addedSet.has(p));\n\n await withTransaction(conn, async () => {\n // DuckDB's ALTER TABLE ADD COLUMN requires a type; VARIANT is the only one that can hold\n // the mixed bigint/number/string/null shapes mapValue() produces for one key across files.\n for (const col of newColumns) await conn.exec(`ALTER TABLE frontmatter ADD COLUMN ${quoteIdent(col)} VARIANT`);\n\n if (parsedDocs.length > 0) {\n const rows = parsedDocs.map((doc) =>\n writableColumns.map((col) => {\n if (col === 'path') return doc.relPath;\n if (col === '_mtime') return doc.mtimeMs;\n if (col === '_ctime') return doc.ctimeMs;\n if (col === '_size') return doc.size;\n if (col === '_parse_error') return doc.parseError;\n return doc.data[col] ?? null;\n })\n );\n await conn.runBatch(insertSql, rows);\n }\n\n const contentTouched = [...vanished, ...reparsedExisting];\n if (contentTouched.length > 0)\n await conn.runBatch(\n 'DELETE FROM content WHERE \"path\" = ?',\n contentTouched.map((p) => [p])\n );\n if (parsedDocs.length > 0) await conn.runBatch(INSERT_CONTENT_SQL, parsedDocs.map(contentRow));\n\n if (vanished.length > 0)\n await conn.runBatch(\n 'DELETE FROM frontmatter WHERE \"path\" = ?',\n vanished.map((p) => [p])\n );\n\n // A preset edit forces a full rebuild, so an unchanged doc's coverage is already correct;\n // new docs have nothing to clear, which keeps cold builds linear.\n const presetTouched = [...vanished, ...reparsedExisting];\n if (presetTouched.length > 0)\n await conn.runBatch(\n 'DELETE FROM preset_files WHERE \"path\" = ?',\n presetTouched.map((p) => [p])\n );\n const presetRows: unknown[][] = [];\n for (const doc of parsedDocs) for (const presetName of doc.presets) presetRows.push([doc.relPath, presetName]);\n if (presetRows.length > 0) await conn.runBatch('INSERT INTO preset_files (\"path\", preset) VALUES (?, ?)', presetRows);\n\n const removedPaths = [...vanished, ...reparsedExisting];\n if (removedPaths.length > 0) for (const feature of features) await feature.remove?.(conn, removedPaths, delta);\n for (const feature of features) {\n const docsForFeature: ExtractedDoc[] = parsedDocs.map((doc) => ({ path: doc.relPath, extracted: doc.extracted[feature.name] }));\n await feature.store?.(conn, docsForFeature, delta);\n }\n for (const feature of features) await feature.afterReconcile?.(conn, delta);\n });\n\n return { parsed: parsedDocs.length, warnings };\n}\n"],"names":["reconcile","CORE_FRONTMATTER_COLUMNS","Set","INSERT_CONTENT_SQL","contentRow","doc","relPath","search","title","summary","text","MAX_FRONTMATTER_COLUMNS","conn","cfg","baseDir","files","currentSet","existingStmt","existingRows","existing","vanished","toReparse","features","seenColumns","report","parsedDocs","warnings","newColumns","col","allColumns","writableColumns","insertSql","added","delta","addedSet","reparsedExisting","listFiles","map","f","prepare","all","Map","r","path","filter","has","row","get","_mtime","mtimeMs","_size","size","length","parsed","activeFeatures","getColumns","progress","reparseFiles","tick","docs","finish","add","SenseError","c","RESERVED_COLUMNS","quoteIdent","join","reparsed","d","p","withTransaction","feature","rows","contentTouched","presetTouched","presetRows","presetName","removedPaths","exec","ctimeMs","parseError","data","runBatch","presets","push","remove","docsForFeature","extracted","name","store","afterReconcile"],"mappings":"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"}
@@ -176,10 +176,8 @@ function registerFunctions(conn) {
176
176
  outputVector.flush();
177
177
  }
178
178
  }));
179
- // segment() rewrites unspaced-script runs into the grapheme phrase FTS5's `_seg` sidecars
180
- // need (see src/text/segment.ts); this store's own lexical index uses contains() instead (D1)
181
- // and never calls this, but hand-written raw SQL naming it still gets the real implementation
182
- // rather than a silent passthrough (PRINCIPLES: no-silent-modes).
179
+ // segment() rewrites unspaced-script runs into the grapheme phrase FTS5's `_seg` sidecars need (text/segment.ts); this store's own
180
+ // lexical index uses contains() instead and never calls this, but hand-written raw SQL naming it gets the real implementation, not a silent passthrough (PRINCIPLES: no-silent-modes).
183
181
  conn.registerScalarFunction(DuckDBScalarFunction.create({
184
182
  name: 'segment',
185
183
  parameterTypes: [
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/duckdb/sql-functions.ts"],"sourcesContent":["import type { DuckDBConnection } from '@duckdb/node-api';\nimport { segmentMatch } from '../../text/segment.ts';\nimport { basenameImpl, hasImpl } from '../sql-functions.ts';\nimport { duckdbApi } from './native.ts';\n\n// Dynamic, not a top-level import: sqlite trees must never even attempt to resolve this optional\n// peer dependency (see open.ts's connect()). Goes through native.ts's shared duckdbApi(), not a\n// bare `import('@duckdb/node-api')` of its own -- by the time this runs, open.ts has already\n// resolved the package, possibly via an on-demand install, and a second independent bare-specifier\n// lookup in the same process would hit Node's stale pre-install resolution miss (see native.ts).\nexport async function registerFunctions(conn: DuckDBConnection): Promise<void> {\n const { DuckDBIntegerType, DuckDBScalarFunction, DuckDBVarCharType } = await duckdbApi();\n conn.registerScalarFunction(\n DuckDBScalarFunction.create({\n name: 'has',\n parameterTypes: [DuckDBVarCharType.instance, DuckDBVarCharType.instance],\n returnType: DuckDBIntegerType.instance,\n mainFunction(_info, inputChunk, outputVector) {\n const fieldVec = inputChunk.getColumnVector(0);\n const valueVec = inputChunk.getColumnVector(1);\n for (let i = 0; i < inputChunk.rowCount; i++) outputVector.setItem(i, hasImpl(fieldVec.getItem(i), valueVec.getItem(i)));\n outputVector.flush();\n },\n })\n );\n conn.registerScalarFunction(\n DuckDBScalarFunction.create({\n name: 'basename',\n parameterTypes: [DuckDBVarCharType.instance],\n varArgsType: DuckDBVarCharType.instance,\n returnType: DuckDBVarCharType.instance,\n mainFunction(_info, inputChunk, outputVector) {\n const pathVec = inputChunk.getColumnVector(0);\n const suffixVec = inputChunk.columnCount > 1 ? inputChunk.getColumnVector(1) : null;\n for (let i = 0; i < inputChunk.rowCount; i++) outputVector.setItem(i, basenameImpl(pathVec.getItem(i), suffixVec ? suffixVec.getItem(i) : undefined));\n outputVector.flush();\n },\n })\n );\n // segment() rewrites unspaced-script runs into the grapheme phrase FTS5's `_seg` sidecars\n // need (see src/text/segment.ts); this store's own lexical index uses contains() instead (D1)\n // and never calls this, but hand-written raw SQL naming it still gets the real implementation\n // rather than a silent passthrough (PRINCIPLES: no-silent-modes).\n conn.registerScalarFunction(\n DuckDBScalarFunction.create({\n name: 'segment',\n parameterTypes: [DuckDBVarCharType.instance],\n returnType: DuckDBVarCharType.instance,\n mainFunction(_info, inputChunk, outputVector) {\n const textVec = inputChunk.getColumnVector(0);\n for (let i = 0; i < inputChunk.rowCount; i++) outputVector.setItem(i, segmentMatch(String(textVec.getItem(i) ?? '')));\n outputVector.flush();\n },\n })\n );\n}\n"],"names":["registerFunctions","conn","DuckDBIntegerType","DuckDBScalarFunction","DuckDBVarCharType","duckdbApi","registerScalarFunction","create","name","parameterTypes","instance","returnType","mainFunction","_info","inputChunk","outputVector","fieldVec","getColumnVector","valueVec","i","rowCount","setItem","hasImpl","getItem","flush","varArgsType","pathVec","suffixVec","columnCount","basenameImpl","undefined","textVec","segmentMatch","String"],"mappings":";;;;+BAUsBA;;;eAAAA;;;yBATO;8BACS;wBACZ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOnB,SAAeA,kBAAkBC,IAAsB;;YACW,MAA/DC,mBAAmBC,sBAAsBC;;;;oBAAsB;;wBAAMC,IAAAA,mBAAS;;;oBAAf,OAAA,eAA/DH,oBAA+D,KAA/DA,mBAAmBC,uBAA4C,KAA5CA,sBAAsBC,oBAAsB,KAAtBA;oBACjDH,KAAKK,sBAAsB,CACzBH,qBAAqBI,MAAM,CAAC;wBAC1BC,MAAM;wBACNC,cAAc;4BAAGL,kBAAkBM,QAAQ;4BAAEN,kBAAkBM,QAAQ;;wBACvEC,YAAYT,kBAAkBQ,QAAQ;wBACtCE,cAAAA,SAAAA,aAAaC,KAAK,EAAEC,UAAU,EAAEC,YAAY;4BAC1C,IAAMC,WAAWF,WAAWG,eAAe,CAAC;4BAC5C,IAAMC,WAAWJ,WAAWG,eAAe,CAAC;4BAC5C,IAAK,IAAIE,IAAI,GAAGA,IAAIL,WAAWM,QAAQ,EAAED,IAAKJ,aAAaM,OAAO,CAACF,GAAGG,IAAAA,uBAAO,EAACN,SAASO,OAAO,CAACJ,IAAID,SAASK,OAAO,CAACJ;4BACpHJ,aAAaS,KAAK;wBACpB;oBACF;oBAEFvB,KAAKK,sBAAsB,CACzBH,qBAAqBI,MAAM,CAAC;wBAC1BC,MAAM;wBACNC,cAAc;4BAAGL,kBAAkBM,QAAQ;;wBAC3Ce,aAAarB,kBAAkBM,QAAQ;wBACvCC,YAAYP,kBAAkBM,QAAQ;wBACtCE,cAAAA,SAAAA,aAAaC,KAAK,EAAEC,UAAU,EAAEC,YAAY;4BAC1C,IAAMW,UAAUZ,WAAWG,eAAe,CAAC;4BAC3C,IAAMU,YAAYb,WAAWc,WAAW,GAAG,IAAId,WAAWG,eAAe,CAAC,KAAK;4BAC/E,IAAK,IAAIE,IAAI,GAAGA,IAAIL,WAAWM,QAAQ,EAAED,IAAKJ,aAAaM,OAAO,CAACF,GAAGU,IAAAA,4BAAY,EAACH,QAAQH,OAAO,CAACJ,IAAIQ,YAAYA,UAAUJ,OAAO,CAACJ,KAAKW;4BAC1If,aAAaS,KAAK;wBACpB;oBACF;oBAEF,0FAA0F;oBAC1F,8FAA8F;oBAC9F,8FAA8F;oBAC9F,kEAAkE;oBAClEvB,KAAKK,sBAAsB,CACzBH,qBAAqBI,MAAM,CAAC;wBAC1BC,MAAM;wBACNC,cAAc;4BAAGL,kBAAkBM,QAAQ;;wBAC3CC,YAAYP,kBAAkBM,QAAQ;wBACtCE,cAAAA,SAAAA,aAAaC,KAAK,EAAEC,UAAU,EAAEC,YAAY;gCAEgDgB;4BAD1F,IAAMA,UAAUjB,WAAWG,eAAe,CAAC;4BAC3C,IAAK,IAAIE,IAAI,GAAGA,IAAIL,WAAWM,QAAQ,EAAED,IAAKJ,aAAaM,OAAO,CAACF,GAAGa,IAAAA,uBAAY,EAACC,QAAOF,mBAAAA,QAAQR,OAAO,CAACJ,gBAAhBY,8BAAAA,mBAAsB;4BAChHhB,aAAaS,KAAK;wBACpB;oBACF;;;;;;IAEJ"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/duckdb/sql-functions.ts"],"sourcesContent":["import type { DuckDBConnection } from '@duckdb/node-api';\nimport { segmentMatch } from '../../text/segment.ts';\nimport { basenameImpl, hasImpl } from '../sql-functions.ts';\nimport { duckdbApi } from './native.ts';\n\n// Dynamic, not a top-level import: sqlite trees must never attempt to resolve this optional peer dependency (open.ts's connect()).\n// Goes through native.ts's shared duckdbApi(), not its own bare import, since a second independent lookup would hit Node's stale pre-install resolution miss.\nexport async function registerFunctions(conn: DuckDBConnection): Promise<void> {\n const { DuckDBIntegerType, DuckDBScalarFunction, DuckDBVarCharType } = await duckdbApi();\n conn.registerScalarFunction(\n DuckDBScalarFunction.create({\n name: 'has',\n parameterTypes: [DuckDBVarCharType.instance, DuckDBVarCharType.instance],\n returnType: DuckDBIntegerType.instance,\n mainFunction(_info, inputChunk, outputVector) {\n const fieldVec = inputChunk.getColumnVector(0);\n const valueVec = inputChunk.getColumnVector(1);\n for (let i = 0; i < inputChunk.rowCount; i++) outputVector.setItem(i, hasImpl(fieldVec.getItem(i), valueVec.getItem(i)));\n outputVector.flush();\n },\n })\n );\n conn.registerScalarFunction(\n DuckDBScalarFunction.create({\n name: 'basename',\n parameterTypes: [DuckDBVarCharType.instance],\n varArgsType: DuckDBVarCharType.instance,\n returnType: DuckDBVarCharType.instance,\n mainFunction(_info, inputChunk, outputVector) {\n const pathVec = inputChunk.getColumnVector(0);\n const suffixVec = inputChunk.columnCount > 1 ? inputChunk.getColumnVector(1) : null;\n for (let i = 0; i < inputChunk.rowCount; i++) outputVector.setItem(i, basenameImpl(pathVec.getItem(i), suffixVec ? suffixVec.getItem(i) : undefined));\n outputVector.flush();\n },\n })\n );\n // segment() rewrites unspaced-script runs into the grapheme phrase FTS5's `_seg` sidecars need (text/segment.ts); this store's own\n // lexical index uses contains() instead and never calls this, but hand-written raw SQL naming it gets the real implementation, not a silent passthrough (PRINCIPLES: no-silent-modes).\n conn.registerScalarFunction(\n DuckDBScalarFunction.create({\n name: 'segment',\n parameterTypes: [DuckDBVarCharType.instance],\n returnType: DuckDBVarCharType.instance,\n mainFunction(_info, inputChunk, outputVector) {\n const textVec = inputChunk.getColumnVector(0);\n for (let i = 0; i < inputChunk.rowCount; i++) outputVector.setItem(i, segmentMatch(String(textVec.getItem(i) ?? '')));\n outputVector.flush();\n },\n })\n );\n}\n"],"names":["registerFunctions","conn","DuckDBIntegerType","DuckDBScalarFunction","DuckDBVarCharType","duckdbApi","registerScalarFunction","create","name","parameterTypes","instance","returnType","mainFunction","_info","inputChunk","outputVector","fieldVec","getColumnVector","valueVec","i","rowCount","setItem","hasImpl","getItem","flush","varArgsType","pathVec","suffixVec","columnCount","basenameImpl","undefined","textVec","segmentMatch","String"],"mappings":";;;;+BAOsBA;;;eAAAA;;;yBANO;8BACS;wBACZ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAInB,SAAeA,kBAAkBC,IAAsB;;YACW,MAA/DC,mBAAmBC,sBAAsBC;;;;oBAAsB;;wBAAMC,IAAAA,mBAAS;;;oBAAf,OAAA,eAA/DH,oBAA+D,KAA/DA,mBAAmBC,uBAA4C,KAA5CA,sBAAsBC,oBAAsB,KAAtBA;oBACjDH,KAAKK,sBAAsB,CACzBH,qBAAqBI,MAAM,CAAC;wBAC1BC,MAAM;wBACNC,cAAc;4BAAGL,kBAAkBM,QAAQ;4BAAEN,kBAAkBM,QAAQ;;wBACvEC,YAAYT,kBAAkBQ,QAAQ;wBACtCE,cAAAA,SAAAA,aAAaC,KAAK,EAAEC,UAAU,EAAEC,YAAY;4BAC1C,IAAMC,WAAWF,WAAWG,eAAe,CAAC;4BAC5C,IAAMC,WAAWJ,WAAWG,eAAe,CAAC;4BAC5C,IAAK,IAAIE,IAAI,GAAGA,IAAIL,WAAWM,QAAQ,EAAED,IAAKJ,aAAaM,OAAO,CAACF,GAAGG,IAAAA,uBAAO,EAACN,SAASO,OAAO,CAACJ,IAAID,SAASK,OAAO,CAACJ;4BACpHJ,aAAaS,KAAK;wBACpB;oBACF;oBAEFvB,KAAKK,sBAAsB,CACzBH,qBAAqBI,MAAM,CAAC;wBAC1BC,MAAM;wBACNC,cAAc;4BAAGL,kBAAkBM,QAAQ;;wBAC3Ce,aAAarB,kBAAkBM,QAAQ;wBACvCC,YAAYP,kBAAkBM,QAAQ;wBACtCE,cAAAA,SAAAA,aAAaC,KAAK,EAAEC,UAAU,EAAEC,YAAY;4BAC1C,IAAMW,UAAUZ,WAAWG,eAAe,CAAC;4BAC3C,IAAMU,YAAYb,WAAWc,WAAW,GAAG,IAAId,WAAWG,eAAe,CAAC,KAAK;4BAC/E,IAAK,IAAIE,IAAI,GAAGA,IAAIL,WAAWM,QAAQ,EAAED,IAAKJ,aAAaM,OAAO,CAACF,GAAGU,IAAAA,4BAAY,EAACH,QAAQH,OAAO,CAACJ,IAAIQ,YAAYA,UAAUJ,OAAO,CAACJ,KAAKW;4BAC1If,aAAaS,KAAK;wBACpB;oBACF;oBAEF,mIAAmI;oBACnI,uLAAuL;oBACvLvB,KAAKK,sBAAsB,CACzBH,qBAAqBI,MAAM,CAAC;wBAC1BC,MAAM;wBACNC,cAAc;4BAAGL,kBAAkBM,QAAQ;;wBAC3CC,YAAYP,kBAAkBM,QAAQ;wBACtCE,cAAAA,SAAAA,aAAaC,KAAK,EAAEC,UAAU,EAAEC,YAAY;gCAEgDgB;4BAD1F,IAAMA,UAAUjB,WAAWG,eAAe,CAAC;4BAC3C,IAAK,IAAIE,IAAI,GAAGA,IAAIL,WAAWM,QAAQ,EAAED,IAAKJ,aAAaM,OAAO,CAACF,GAAGa,IAAAA,uBAAY,EAACC,QAAOF,mBAAAA,QAAQR,OAAO,CAACJ,gBAAhBY,8BAAAA,mBAAsB;4BAChHhB,aAAaS,KAAK;wBACpB;oBACF;;;;;;IAEJ"}
@@ -380,9 +380,8 @@ function createStore(instance, duckdb, conn, cfg, baseDir) {
380
380
  lexical: {
381
381
  query: lex.query
382
382
  },
383
- // The column's fixed DDL width (STORE_DIMS) is what every scan binds against, not the
384
- // interface's per-call storeDims -- see vectors.ts's padded() for why a shorter vector is
385
- // still correct against a wider column.
383
+ // The column's fixed DDL width (STORE_DIMS) is what every scan binds against, not the interface's per-call storeDims --
384
+ // see vectors.ts's padded() for why a shorter vector remains correct against a wider column.
386
385
  vectors: {
387
386
  pending: function pending() {
388
387
  return (0, _vectorsts.pendingRows)(conn);
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/duckdb/store.ts"],"sourcesContent":["import type { DuckDBConnection, DuckDBInstance } from '@duckdb/node-api';\nimport type { Config } from '../../config/index.ts';\nimport { STORE_DIMS } from '../../embed/types.ts';\nimport { getColumns } from '../shared.ts';\nimport { withTransaction } from '../transaction.ts';\nimport type { Capability, Connection, Statement, Store } from '../types.ts';\nimport { hasVectorRow, pendingRows } from '../vectors.ts';\nimport { storeRowToJs } from './connection.ts';\nimport { fieldStats } from './fieldStats.ts';\nimport { createLexicalIndex } from './lexical.ts';\nimport { reconcile } from './reconcile.ts';\nimport { scanCandidates, scanSimilar, writeVectorBatch } from './vectors.ts';\n\n// Portable surface, links/sections/tags/rank, raw sql passthrough, lexical (D1: fts BM25 +\n// contains(), see lexical.ts), and vectors (D2: native FLOAT[N] + array_cosine_similarity, see\n// vectors.ts) are implemented. 'snippets' is declined: no snippet()-equivalent exists, so every\n// lexical hit relies on the caller's JS excerpt fallback (commands/search.ts) rather than a\n// bounded engine-native one. 'phrases' means quoted-phrase matching only (types.ts):\n// prefix/boolean/NEAR/column-filter FTS5 syntax is not claimed here -- lexical.ts rejects it\n// rather than answer it differently.\nexport const CAPABILITIES: ReadonlySet<Capability> = new Set(['lexical', 'phrases', 'vectors']);\n\n// Shares one Connection instance (conn) with open()'s own reconcile call so transaction depth\n// (see transaction.ts) is tracked against the same object everywhere. The instance is the\n// native database handle that owns the WAL: close() must close it, not just disconnect the\n// connection, or DuckDB never checkpoints and the next open reads a mismatched WAL.\nexport function createStore(instance: DuckDBInstance, duckdb: DuckDBConnection, conn: Connection, cfg: Config, baseDir: string): Store {\n const lex = createLexicalIndex(conn);\n return {\n name: 'duckdb',\n capabilities: CAPABILITIES,\n async exec(sql: string): Promise<void> {\n await conn.exec(sql);\n },\n async prepare(sql: string): Promise<Statement> {\n return conn.prepare(sql);\n },\n async runBatch(sql: string, paramRows: unknown[][]): Promise<void> {\n await conn.runBatch(sql, paramRows);\n },\n async transaction<T>(fn: () => Promise<T>): Promise<T> {\n return withTransaction(conn, fn);\n },\n async reconcile() {\n const result = await reconcile(conn, cfg, baseDir);\n // content may have changed; the fts index is rebuilt lazily, on the next lexical query\n // that needs it, not here (see lexical.ts's FtsIndexState).\n lex.markStale();\n return result;\n },\n docs: {\n async columns() {\n return [...(await getColumns(conn))];\n },\n fieldStats: (columns, scopeWhere) => fieldStats(conn, columns, scopeWhere),\n },\n lexical: {\n query: lex.query,\n },\n // The column's fixed DDL width (STORE_DIMS) is what every scan binds against, not the\n // interface's per-call storeDims -- see vectors.ts's padded() for why a shorter vector is\n // still correct against a wider column.\n vectors: {\n pending: () => pendingRows(conn),\n writeVectors: (rows) => writeVectorBatch(duckdb, conn, STORE_DIMS, rows),\n candidates: (qv, _storeDims, fetch, allowed) => scanCandidates(duckdb, qv, STORE_DIMS, fetch, allowed),\n similar: (path, opts) => scanSimilar(duckdb, conn, STORE_DIMS, path, opts),\n hasVector: (path) => hasVectorRow(conn, path),\n },\n // No comparable setting to report yet.\n async engineStatus() {\n return {};\n },\n raw: {\n async prepare(sql: string) {\n const prepared = await duckdb.prepare(sql);\n return {\n columns: () => {\n const out: Array<{ name: string }> = [];\n for (let i = 0; i < prepared.columnCount; i++) out.push({ name: prepared.columnName(i) });\n return out;\n },\n // Real incremental streaming: DuckDB reads its own result in row-group chunks, so\n // each readUntil only fetches what isn't already in hand.\n iterate: async function* (...params: unknown[]) {\n if (params.length > 0) prepared.bind(params as Parameters<typeof prepared.bind>[0]);\n const reader = await prepared.streamAndRead();\n let yielded = 0;\n do {\n await reader.readUntil(reader.currentRowCount + 2048);\n const rows = reader.getRowObjectsJS() as Array<Record<string, unknown>>;\n for (; yielded < rows.length; yielded++) yield storeRowToJs(rows[yielded]);\n } while (!reader.done);\n },\n };\n },\n },\n async close() {\n // Order matters: the connection must be gone before the instance closes the WAL.\n duckdb.disconnectSync();\n instance.closeSync();\n },\n };\n}\n"],"names":["CAPABILITIES","createStore","Set","instance","duckdb","conn","cfg","baseDir","lex","createLexicalIndex","name","capabilities","exec","sql","prepare","runBatch","paramRows","transaction","fn","withTransaction","reconcile","result","markStale","docs","columns","getColumns","fieldStats","scopeWhere","lexical","query","vectors","pending","pendingRows","writeVectors","rows","writeVectorBatch","STORE_DIMS","candidates","qv","_storeDims","fetch","allowed","scanCandidates","similar","path","opts","scanSimilar","hasVector","hasVectorRow","engineStatus","raw","prepared","out","i","columnCount","push","columnName","iterate","params","reader","yielded","length","bind","streamAndRead","readUntil","currentRowCount","getRowObjectsJS","storeRowToJs","done","close","disconnectSync","closeSync"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/duckdb/store.ts"],"sourcesContent":["import type { DuckDBConnection, DuckDBInstance } from '@duckdb/node-api';\nimport type { Config } from '../../config/index.ts';\nimport { STORE_DIMS } from '../../embed/types.ts';\nimport { getColumns } from '../shared.ts';\nimport { withTransaction } from '../transaction.ts';\nimport type { Capability, Connection, Statement, Store } from '../types.ts';\nimport { hasVectorRow, pendingRows } from '../vectors.ts';\nimport { storeRowToJs } from './connection.ts';\nimport { fieldStats } from './fieldStats.ts';\nimport { createLexicalIndex } from './lexical.ts';\nimport { reconcile } from './reconcile.ts';\nimport { scanCandidates, scanSimilar, writeVectorBatch } from './vectors.ts';\n\n// Portable surface, links/sections/tags/rank, raw sql passthrough, lexical (fts BM25 + contains(), lexical.ts), and vectors (native\n// FLOAT[N] + array_cosine_similarity, vectors.ts) are implemented. 'snippets' is declined (JS excerpt fallback handles it); 'phrases' means quoted-phrase only -- FTS5 operator syntax is rejected, not answered differently.\nexport const CAPABILITIES: ReadonlySet<Capability> = new Set(['lexical', 'phrases', 'vectors']);\n\n// Shares one Connection instance (conn) with open()'s own reconcile call so transaction depth (transaction.ts) is tracked against the same object everywhere.\n// The instance is the native handle that owns the WAL: close() must close it, not just disconnect, or DuckDB never checkpoints and the next open reads a mismatched WAL.\nexport function createStore(instance: DuckDBInstance, duckdb: DuckDBConnection, conn: Connection, cfg: Config, baseDir: string): Store {\n const lex = createLexicalIndex(conn);\n return {\n name: 'duckdb',\n capabilities: CAPABILITIES,\n async exec(sql: string): Promise<void> {\n await conn.exec(sql);\n },\n async prepare(sql: string): Promise<Statement> {\n return conn.prepare(sql);\n },\n async runBatch(sql: string, paramRows: unknown[][]): Promise<void> {\n await conn.runBatch(sql, paramRows);\n },\n async transaction<T>(fn: () => Promise<T>): Promise<T> {\n return withTransaction(conn, fn);\n },\n async reconcile() {\n const result = await reconcile(conn, cfg, baseDir);\n // content may have changed; the fts index is rebuilt lazily, on the next lexical query\n // that needs it, not here (see lexical.ts's FtsIndexState).\n lex.markStale();\n return result;\n },\n docs: {\n async columns() {\n return [...(await getColumns(conn))];\n },\n fieldStats: (columns, scopeWhere) => fieldStats(conn, columns, scopeWhere),\n },\n lexical: {\n query: lex.query,\n },\n // The column's fixed DDL width (STORE_DIMS) is what every scan binds against, not the interface's per-call storeDims --\n // see vectors.ts's padded() for why a shorter vector remains correct against a wider column.\n vectors: {\n pending: () => pendingRows(conn),\n writeVectors: (rows) => writeVectorBatch(duckdb, conn, STORE_DIMS, rows),\n candidates: (qv, _storeDims, fetch, allowed) => scanCandidates(duckdb, qv, STORE_DIMS, fetch, allowed),\n similar: (path, opts) => scanSimilar(duckdb, conn, STORE_DIMS, path, opts),\n hasVector: (path) => hasVectorRow(conn, path),\n },\n // No comparable setting to report yet.\n async engineStatus() {\n return {};\n },\n raw: {\n async prepare(sql: string) {\n const prepared = await duckdb.prepare(sql);\n return {\n columns: () => {\n const out: Array<{ name: string }> = [];\n for (let i = 0; i < prepared.columnCount; i++) out.push({ name: prepared.columnName(i) });\n return out;\n },\n // Real incremental streaming: DuckDB reads its own result in row-group chunks, so\n // each readUntil only fetches what isn't already in hand.\n iterate: async function* (...params: unknown[]) {\n if (params.length > 0) prepared.bind(params as Parameters<typeof prepared.bind>[0]);\n const reader = await prepared.streamAndRead();\n let yielded = 0;\n do {\n await reader.readUntil(reader.currentRowCount + 2048);\n const rows = reader.getRowObjectsJS() as Array<Record<string, unknown>>;\n for (; yielded < rows.length; yielded++) yield storeRowToJs(rows[yielded]);\n } while (!reader.done);\n },\n };\n },\n },\n async close() {\n // Order matters: the connection must be gone before the instance closes the WAL.\n duckdb.disconnectSync();\n instance.closeSync();\n },\n };\n}\n"],"names":["CAPABILITIES","createStore","Set","instance","duckdb","conn","cfg","baseDir","lex","createLexicalIndex","name","capabilities","exec","sql","prepare","runBatch","paramRows","transaction","fn","withTransaction","reconcile","result","markStale","docs","columns","getColumns","fieldStats","scopeWhere","lexical","query","vectors","pending","pendingRows","writeVectors","rows","writeVectorBatch","STORE_DIMS","candidates","qv","_storeDims","fetch","allowed","scanCandidates","similar","path","opts","scanSimilar","hasVector","hasVectorRow","engineStatus","raw","prepared","out","i","columnCount","push","columnName","iterate","params","reader","yielded","length","bind","streamAndRead","readUntil","currentRowCount","getRowObjectsJS","storeRowToJs","done","close","disconnectSync","closeSync"],"mappings":"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"}
@@ -175,24 +175,15 @@ function _unsupported_iterable_to_array(o, minLen) {
175
175
  if (n === "Map" || n === "Set") return Array.from(n);
176
176
  if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
177
177
  }
178
- // This store keeps vectors as native FLOAT[dims] arrays (dims fixed at DDL time by
179
- // duckdb/open.ts's ensureSchema, from embed/types.ts's STORE_DIMS) and scans them with
180
- // array_cosine_similarity, pushing top-k into SQL instead of pulling every row into JS --
181
- // sqlite's int8+scale BLOB scan (src/store/sqlite/vectors.ts) is the other store's own
182
- // representation and stays as it is. Every function here takes `dims` as a parameter rather
183
- // than importing STORE_DIMS directly, so it is testable at any width (store.ts wires the real
184
- // constant at the call site).
185
- //
186
- // A value import of '@duckdb/node-api' must never sit at module top level, or a sqlite-only
187
- // tree would resolve this optional dependency just by importing store/index.ts -- native.ts's
188
- // shared duckdbApi() (not a bare import of its own) is what keeps that lazy and reuses whatever
189
- // open.ts already resolved, including via an on-demand install (see native.ts).
178
+ // 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
179
+ // 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.
180
+ // A value import of '@duckdb/node-api' must never sit at module top level, or a sqlite-only tree would resolve this optional dependency
181
+ // just by importing store/index.ts; native.ts's shared duckdbApi() keeps that lazy and reuses whatever open.ts already resolved.
190
182
  // A bind position whose type is left to auto-inference (safe for plain strings/numbers; only
191
183
  // the vector ARRAY positions below need an explicit type -- see writeVectorBatch's comment).
192
184
  var untyped = undefined;
193
- // The DDL-fixed array width can exceed a vector's actual length (a hypothetical model sliced
194
- // under the column's width); zero-padding leaves cosine scores unchanged since the added
195
- // dimensions contribute nothing to either vector's dot product or norm.
185
+ // The DDL-fixed array width can exceed a vector's actual length (a hypothetical model sliced under the column's width);
186
+ // zero-padding leaves cosine scores unchanged since the added dimensions contribute nothing to either vector's dot product or norm.
196
187
  function padded(values, dims) {
197
188
  var out = new Array(dims).fill(0);
198
189
  for(var d = 0; d < Math.min(values.length, dims); d++)out[d] = values[d];
@@ -205,9 +196,8 @@ function inClause(column, count) {
205
196
  return '?';
206
197
  }).join(', '), ")");
207
198
  }
208
- // Rows arrive int8-quantized with a per-vector scale (the wire format embed/query.ts produces
209
- // for every store, see toStore); dequantizing into a plain float array is this store's own
210
- // representation choice, so both stores are handed the same vectors and diverge only here.
199
+ // Rows arrive int8-quantized with a per-vector scale (the wire format embed/query.ts produces for every store, see toStore);
200
+ // 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.
211
201
  function dequantize(row, dims) {
212
202
  var q = new Int8Array(row.vector.buffer, row.vector.byteOffset, row.vector.byteLength);
213
203
  return padded(Array.from(q, function(v) {
@@ -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\n// duckdb/open.ts's ensureSchema, from embed/types.ts's STORE_DIMS) and scans them with\n// array_cosine_similarity, pushing top-k into SQL instead of pulling every row into JS --\n// sqlite's int8+scale BLOB scan (src/store/sqlite/vectors.ts) is the other store's own\n// representation and stays as it is. Every function here takes `dims` as a parameter rather\n// than importing STORE_DIMS directly, so it is testable at any width (store.ts wires the real\n// constant at the call site).\n//\n// A value import of '@duckdb/node-api' must never sit at module top level, or a sqlite-only\n// tree would resolve this optional dependency just by importing store/index.ts -- native.ts's\n// shared duckdbApi() (not a bare import of its own) is what keeps that lazy and reuses whatever\n// open.ts already resolved, including via an on-demand install (see native.ts).\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\n// under the column's width); zero-padding leaves cosine scores unchanged since the added\n// 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\n// for every store, see toStore); dequantizing into a plain float array is this store's own\n// 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\n// rewriteUpdate, the same rewrite Connection.runBatch uses), bound directly against the native\n// connection because the vector column needs an explicit ARRAY(DOUBLE, dims) bind type --\n// automatic type inference on the raw values misreads an all-integer first component (a real\n// vector's exact 0.0 is common) as an INTEGER array and silently truncates the rest of the row\n// (verified against a live connection: 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, its line range riding along, entirely in SQL: arg_max picks\n// the winning chunk's line range from the same row max(score) came from, per path. An empty\n// `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 sql = `SELECT \"path\", arg_max(start_line, score) AS start_line, arg_max(end_line, score) AS end_line, max(score) AS score\n FROM (\n SELECT \"path\", start_line, end_line, array_cosine_similarity(vector, ?) AS score\n FROM embeddings\n WHERE vector IS NOT NULL ${allowed ? `AND ${inClause('\"path\"', allowedList.length)}` : ''}\n ) sub\n GROUP BY \"path\"\n ORDER BY score DESC\n LIMIT ?`;\n const stmt = await duckdb.prepare(sql);\n try {\n const values: DuckDBValue[] = [arrayValue(padded(qv, dims)), ...allowedList, fetch];\n const types: DuckDBType[] = [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\n// into one native scan: the sampled target vectors become a small VALUES list, cross-joined\n// against every stored vector and reduced with max()/GROUP BY, so the O(target x stored) cost\n// the plan measures (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(', ')})\n SELECT e.\"path\" AS path, max(array_cosine_similarity(e.vector, t.tv)) 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 ORDER BY score DESC\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","reader","size","map","runAndReadAll","getRowObjectsJS","r","lines","start_line","end_line","similarity","asCosine","score","opts","targetStmt","targetRows","targets","excludeList","all","sampleEvenly","exclude","t","k"],"mappings":";;;;;;;;;;;QAgFsBA;eAAAA;;QA8BAC;eAAAA;;QAxDAC;eAAAA;;;6BArDU;yBAEO;uBACT;wBACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAE1B,mFAAmF;AACnF,uFAAuF;AACvF,0FAA0F;AAC1F,uFAAuF;AACvF,4FAA4F;AAC5F,8FAA8F;AAC9F,8BAA8B;AAC9B,EAAE;AACF,4FAA4F;AAC5F,8FAA8F;AAC9F,gGAAgG;AAChG,gFAAgF;AAEhF,6FAA6F;AAC7F,6FAA6F;AAC7F,IAAMC,UAAUC;AAEhB,6FAA6F;AAC7F,yFAAyF;AACzF,wEAAwE;AACxE,SAASC,OAAOC,MAAyB,EAAEC,IAAY;IACrD,IAAMC,MAAM,IAAIC,MAAcF,MAAMG,IAAI,CAAC;IACzC,IAAK,IAAIC,IAAI,GAAGA,IAAIC,KAAKC,GAAG,CAACP,OAAOQ,MAAM,EAAEP,OAAOI,IAAKH,GAAG,CAACG,EAAE,GAAGL,MAAM,CAACK,EAAE;IAC1E,OAAOH;AACT;AAEA,SAASO,SAASC,MAAc,EAAEC,KAAa;IAC7C,OAAO,AAAC,GAAgBR,OAAdO,QAAO,SAA2D,OAApDP,MAAMS,IAAI,CAAC;QAAEJ,QAAQG;IAAM,GAAG;eAAM;OAAKE,IAAI,CAAC,OAAM;AAC9E;AAEA,8FAA8F;AAC9F,2FAA2F;AAC3F,2FAA2F;AAC3F,SAASC,WAAWC,GAAmB,EAAEd,IAAY;IACnD,IAAMe,IAAI,IAAIC,UAAUF,IAAIG,MAAM,CAACC,MAAM,EAAEJ,IAAIG,MAAM,CAACE,UAAU,EAAEL,IAAIG,MAAM,CAACG,UAAU;IACvF,OAAOtB,OACLI,MAAMS,IAAI,CAACI,GAAG,SAACM;eAAMA,IAAIP,IAAIQ,KAAK;QAClCtB;AAEJ;AAQO,SAAeL,iBAAiB4B,MAAwB,EAAEC,IAAgB,EAAExB,IAAY,EAAEyB,IAAsB;;YAE/E,MAA9BC,YAAYC,OAAOC,QACrBC;;;;oBAFN,IAAIJ,KAAKlB,MAAM,KAAK,GAAG;;;oBACe;;wBAAMuB,IAAAA,mBAAS;;;oBAAf,OAAA,eAA9BJ,aAA8B,KAA9BA,YAAYC,QAAkB,KAAlBA,OAAOC,SAAW,KAAXA;oBACrBC,YAAYE,IAAAA,sBAAa,EAAC,mEAAmEN,KAAKlB,MAAM;oBAC9G,IAAI,CAACsB,WAAW,MAAM,IAAIG,MAAM;oBAEhC;;wBAAMC,IAAAA,8BAAe,EAACT,MAAM;;oCACpBU,MAEEnC,QACAoC,OACD,2BAAA,mBAAA,gBAAA,WAAA,OAAMrB;;;;4CAJA;;gDAAMS,OAAOa,OAAO,CAACP,UAAUQ,GAAG;;;4CAAzCH,OAAO;;;;;;;;;4CAELnC;4CACAoC;4CACD,kCAAA,2BAAA;;gDAAL,IAAK,YAAaV,2BAAb,6BAAA,QAAA,yBAAA,iCAAmB;oDAAbX,MAAN;oDACHf,OAAOuC,IAAI,CAACZ,WAAWb,WAAWC,KAAKd,QAAQc,IAAIyB,IAAI,EAAEzB,IAAI0B,KAAK;oDAClEL,MAAMG,IAAI,CAACX,MAAMC,QAAQ5B,OAAOJ,SAASA;gDAC3C;;gDAHK;gDAAA;;;yDAAA,6BAAA;wDAAA;;;wDAAA;8DAAA;;;;4CAILsC,KAAKO,IAAI,CAAC1C,QAAQoC;4CAClB;;gDAAMD,KAAKQ,GAAG;;;4CAAd;;;;;;4CAEAR,KAAKS,WAAW;;;;;;;;;;4BAEpB;;;;oBAdA;;;;;;IAeF;;AAKO,SAAelD,eAAe8B,MAAwB,EAAEqB,EAAgB,EAAE5C,IAAY,EAAE6C,KAAa,EAAEC,OAAqB;;YAE3F,MAA9BpB,YAAYC,OAAOC,QACrBmB,aACAV,KASAH,MAEEnC,QACAoC,OAEAa,QACAvB;;;;oBAlBR,IAAIqB,WAAWA,QAAQG,IAAI,KAAK,GAAG;;;;oBACG;;wBAAMnB,IAAAA,mBAAS;;;oBAAf,OAAA,eAA9BJ,aAA8B,KAA9BA,YAAYC,QAAkB,KAAlBA,OAAOC,SAAW,KAAXA;oBACrBmB,cAAcD,UAAW,qBAAGA;oBAC5BT,MAAM,AAAC,iRAIiF,OAA/DS,UAAU,AAAC,OAA6C,OAAvCtC,SAAS,UAAUuC,YAAYxC,MAAM,KAAM,IAAG;oBAKjF;;wBAAMgB,OAAOa,OAAO,CAACC;;;oBAA5BH,OAAO;;;;;;;;;oBAELnC,SAAwB;wBAAC2B,WAAW5B,OAAO8C,IAAI5C;sBAAvB,OAA+B,qBAAG+C;wBAAaF;;oBACvEV,QAAsB;wBAACR,MAAMC,QAAQ5B;sBAAf,OAAsB,qBAAG+C,YAAYG,GAAG,CAAC;+BAAMtD;;wBAAUA;;oBACrFsC,KAAKO,IAAI,CAAC1C,QAAQoC;oBACH;;wBAAMD,KAAKiB,aAAa;;;oBAAjCH,SAAS;oBACTvB,OAAOuB,OAAOI,eAAe;oBACnC;;wBAAO3B,KAAKyB,GAAG,CAAC,SAACG;mCAAO;gCAAEd,MAAMc,EAAEd,IAAI;gCAAEe,OAAO,AAAC,IAAmBD,OAAhBA,EAAEE,UAAU,EAAC,KAAc,OAAXF,EAAEG,QAAQ;gCAAIC,YAAYC,IAAAA,mBAAQ,EAACL,EAAEM,KAAK;4BAAE;;;;oBAE/GzB,KAAKS,WAAW;;;;;;;;;;IAEpB;;AAMO,SAAejD,YAAY6B,MAAwB,EAAEC,IAAgB,EAAExB,IAAY,EAAEuC,IAAY,EAAEqB,IAAgE;;YAElKC,YACAC,YAEAC,SAEgC,MAA9BrC,YAAYC,OAAOC,QACrBoC,aACAjB,aACAV,KASAH,MAEEnC,QACAoC,OAEAa,QACAvB;;;;oBAxBR,IAAImC,KAAKd,OAAO,IAAIc,KAAKd,OAAO,CAACG,IAAI,KAAK,GAAG;;;;oBAC1B;;wBAAMzB,KAAKY,OAAO,CAAC;;;oBAAhCyB,aAAa;oBACC;;wBAAMA,WAAWI,GAAG,CAAC1B;;;oBAAnCuB,aAAc;oBACpB,IAAIA,WAAWvD,MAAM,KAAK,GAAG;;;;oBACvBwD,UAAUG,IAAAA,uBAAY,EAACJ,YAAYZ,GAAG,CAAC,SAACpC;+BAAQA,IAAIG,MAAM;;oBAE1B;;wBAAMa,IAAAA,mBAAS;;;oBAAf,OAAA,eAA9BJ,aAA8B,KAA9BA,YAAYC,QAAkB,KAAlBA,OAAOC,SAAW,KAAXA;oBACrBoC,cAAe,qBAAGJ,KAAKO,OAAO;oBAC9BpB,cAAca,KAAKd,OAAO,GAAI,qBAAGc,KAAKd,OAAO;oBAC7CT,MAAM,AAAC,+BAIP2B,OAJqCD,QAAQb,GAAG,CAAC;+BAAM;uBAAOtC,IAAI,CAAC,OAAM,qLAKzEgD,OADAI,YAAYzD,MAAM,GAAG,IAAI,AAAC,WAAmD,OAAzCC,SAAS,YAAYwD,YAAYzD,MAAM,KAAM,IAAG,YACd,OAAtEqD,KAAKd,OAAO,GAAG,AAAC,OAA+C,OAAzCtC,SAAS,YAAYuC,YAAYxC,MAAM,KAAM,IAAG;oBAI/D;;wBAAMgB,OAAOa,OAAO,CAACC;;;oBAA5BH,OAAO;;;;;;;;;oBAELnC,SAAwB,AAAC,qBAAGgE,QAAQb,GAAG,CAAC,SAACkB;+BAAM1C,WAAW5B,OAAOsE,GAAGpE;;wBAASuC;uBAAM,qBAAGyB,cAAa,qBAAGjB;wBAAaa,KAAKS,CAAC;;oBACzHlC,QAAsB,AAAC,qBAAG4B,QAAQb,GAAG,CAAC;+BAAMvB,MAAMC,QAAQ5B;;wBAAQJ;uBAAS,qBAAGoE,YAAYd,GAAG,CAAC;+BAAMtD;yBAAU,qBAAGmD,YAAYG,GAAG,CAAC;+BAAMtD;;wBAAUA;;oBACvJsC,KAAKO,IAAI,CAAC1C,QAAQoC;oBACH;;wBAAMD,KAAKiB,aAAa;;;oBAAjCH,SAAS;oBACTvB,OAAOuB,OAAOI,eAAe;oBACnC;;wBAAO3B,KAAKyB,GAAG,CAAC,SAACG;mCAAO;gCAAEd,MAAMc,EAAEd,IAAI;gCAAEkB,YAAYC,IAAAA,mBAAQ,EAACL,EAAEM,KAAK;4BAAE;;;;oBAEtEzB,KAAKS,WAAW;;;;;;;;;;IAEpB"}
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, its line range riding along, entirely in SQL: arg_max picks the winning chunk's line range from the same row max(score) came from, per path.\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 sql = `SELECT \"path\", arg_max(start_line, score) AS start_line, arg_max(end_line, score) AS end_line, max(score) AS score\n FROM (\n SELECT \"path\", start_line, end_line, array_cosine_similarity(vector, ?) AS score\n FROM embeddings\n WHERE vector IS NOT NULL ${allowed ? `AND ${inClause('\"path\"', allowedList.length)}` : ''}\n ) sub\n GROUP BY \"path\"\n ORDER BY score DESC\n LIMIT ?`;\n const stmt = await duckdb.prepare(sql);\n try {\n const values: DuckDBValue[] = [arrayValue(padded(qv, dims)), ...allowedList, fetch];\n const types: DuckDBType[] = [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(', ')})\n SELECT e.\"path\" AS path, max(array_cosine_similarity(e.vector, t.tv)) 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 ORDER BY score DESC\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","reader","size","map","runAndReadAll","getRowObjectsJS","r","lines","start_line","end_line","similarity","asCosine","score","opts","targetStmt","targetRows","targets","excludeList","all","sampleEvenly","exclude","t","k"],"mappings":"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"}
@@ -2,7 +2,8 @@ import type { ResolvedConfig } from '../config/index.js';
2
2
  import type { OpenResult } from './sqlite/open.js';
3
3
  export declare function openStore(cfg: ResolvedConfig): Promise<OpenResult>;
4
4
  export declare function requireWatchConcurrency(cfg: ResolvedConfig): void;
5
- export { getMeta, setMeta } from './meta.js';
5
+ export { clearCache } from './cache.js';
6
+ export { getMeta, setMeta } from './shared.js';
6
7
  export type { OpenResult } from './sqlite/open.js';
7
- export { clearCache, DB_FILENAME, docCount, SCHEMA_VERSION } from './sqlite/open.js';
8
+ export { DB_FILENAME, docCount, SCHEMA_VERSION } from './sqlite/open.js';
8
9
  export type { Capability, Connection, DocumentStore, LexicalHit, LexicalIndex, LexicalQueryOptions, RawStatement, RunResult, SqlSession, Statement, Store, VectorCandidate, VectorSimilar, VectorStore, VectorWriteRow } from './types.js';
@@ -2,7 +2,8 @@ import type { ResolvedConfig } from '../config/index.js';
2
2
  import type { OpenResult } from './sqlite/open.js';
3
3
  export declare function openStore(cfg: ResolvedConfig): Promise<OpenResult>;
4
4
  export declare function requireWatchConcurrency(cfg: ResolvedConfig): void;
5
- export { getMeta, setMeta } from './meta.js';
5
+ export { clearCache } from './cache.js';
6
+ export { getMeta, setMeta } from './shared.js';
6
7
  export type { OpenResult } from './sqlite/open.js';
7
- export { clearCache, DB_FILENAME, docCount, SCHEMA_VERSION } from './sqlite/open.js';
8
+ export { DB_FILENAME, docCount, SCHEMA_VERSION } from './sqlite/open.js';
8
9
  export type { Capability, Connection, DocumentStore, LexicalHit, LexicalIndex, LexicalQueryOptions, RawStatement, RunResult, SqlSession, Statement, Store, VectorCandidate, VectorSimilar, VectorStore, VectorWriteRow } from './types.js';
@@ -18,13 +18,13 @@ _export(exports, {
18
18
  return _opents1.SCHEMA_VERSION;
19
19
  },
20
20
  get clearCache () {
21
- return _opents1.clearCache;
21
+ return _cachets.clearCache;
22
22
  },
23
23
  get docCount () {
24
24
  return _opents1.docCount;
25
25
  },
26
26
  get getMeta () {
27
- return _metats.getMeta;
27
+ return _sharedts.getMeta;
28
28
  },
29
29
  get openStore () {
30
30
  return openStore;
@@ -33,7 +33,7 @@ _export(exports, {
33
33
  return requireWatchConcurrency;
34
34
  },
35
35
  get setMeta () {
36
- return _metats.setMeta;
36
+ return _sharedts.setMeta;
37
37
  }
38
38
  });
39
39
  var _indexts = require("../config/index.js");
@@ -44,7 +44,8 @@ var _opents1 = require("./sqlite/open.js");
44
44
  var _storets1 = require("./sqlite/store.js");
45
45
  var _opents2 = require("./turso/open.js");
46
46
  var _storets2 = require("./turso/store.js");
47
- var _metats = require("./meta.js");
47
+ var _cachets = require("./cache.js");
48
+ var _sharedts = require("./shared.js");
48
49
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
49
50
  try {
50
51
  var info = gen[key](arg);
@@ -197,10 +198,8 @@ function openStore(cfg) {
197
198
  return _ts_generator(this, function(_state) {
198
199
  name = (0, _indexts.storeName)(cfg);
199
200
  entry = entryFor(name);
200
- // The one unambiguous, config-level capability need: an embed block some preset actually
201
- // uses for vectors. Word/lexical search has no equivalent unambiguous signal at this level
202
- // (every preset defaults to wanting "words"), so a store lacking 'lexical' fails loudly at
203
- // first use instead (see duckdb/store.ts's lexical.query()).
201
+ // The one unambiguous, config-level capability need: an embed block some preset actually uses
202
+ // 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.
204
203
  if ((0, _indexts.anyPresetEmbeds)(cfg) && !entry.capabilities.has('vectors')) {
205
204
  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)'));
206
205
  }
@@ -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 './sqlite/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\n // uses for vectors. Word/lexical search has no equivalent unambiguous signal at this level\n // (every preset defaults to wanting \"words\"), so a store lacking 'lexical' fails loudly at\n // first use instead (see duckdb/store.ts's lexical.query()).\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// 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 { getMeta, setMeta } from './meta.ts';\nexport type { OpenResult } from './sqlite/open.ts';\nexport { clearCache, DB_FILENAME, docCount, 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';\n"],"names":["DB_FILENAME","SCHEMA_VERSION","clearCache","docCount","getMeta","openStore","requireWatchConcurrency","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;;;;;;;;;;;;QA2DlCA;eAAAA,oBAAW;;QAAYC;eAAAA,uBAAc;;QAAjDC;eAAAA,mBAAU;;QAAeC;eAAAA,iBAAQ;;QAFjCC;eAAAA,eAAO;;QAxBMC;eAAAA;;QAiBNC;eAAAA;;QAOEC;eAAAA,eAAO;;;uBAtDkB;wBAChB;sBACA;uBACyB;uBAEzB;wBACyB;uBAC1B;wBACyB;sBA8ClB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAtCjC,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,SAAejB,UAAUsB,GAAmB;;YAC3CN,MACAC;;YADAD,OAAOO,IAAAA,kBAAS,EAACD;YACjBL,QAAQF,SAASC;YAEvB,yFAAyF;YACzF,2FAA2F;YAC3F,2FAA2F;YAC3F,6DAA6D;YAC7D,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;;AAIO,SAASrB,wBAAwBqB,GAAmB;IACzD,IAAMN,OAAOO,IAAAA,kBAAS,EAACD;IACvB,IAAI,CAACP,SAASC,MAAMX,YAAY,CAACoB,GAAG,CAAC,sBAAsB;QACzD,MAAM,IAAIP,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 './sqlite/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\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 { getMeta, setMeta } from './shared.ts';\nexport type { OpenResult } from './sqlite/open.ts';\nexport { DB_FILENAME, docCount, 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';\n"],"names":["DB_FILENAME","SCHEMA_VERSION","clearCache","docCount","getMeta","openStore","requireWatchConcurrency","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;;;;;;;;;;;;QA0D9CA;eAAAA,oBAAW;;QAAYC;eAAAA,uBAAc;;QAHrCC;eAAAA,mBAAU;;QAGGC;eAAAA,iBAAQ;;QAFrBC;eAAAA,iBAAO;;QAvBMC;eAAAA;;QAeNC;eAAAA;;QAQEC;eAAAA,iBAAO;;;uBArDkB;wBAChB;sBACA;uBACyB;uBAEzB;wBACyB;uBAC1B;wBACyB;uBA4CxB;wBACM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AArCjC,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,SAAejB,UAAUsB,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;;AAIO,SAASrB,wBAAwBqB,GAAmB;IACzD,IAAMN,OAAOO,IAAAA,kBAAS,EAACD;IACvB,IAAI,CAACP,SAASC,MAAMX,YAAY,CAACoB,GAAG,CAAC,sBAAsB;QACzD,MAAM,IAAIP,oBAAU,CAAC,4BAA4B,AAAC,UAAc,OAALF,MAAK;IAClE;AACF"}
@@ -208,10 +208,8 @@ function _unsupported_iterable_to_array(o, minLen) {
208
208
  if (n === "Map" || n === "Set") return Array.from(n);
209
209
  if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
210
210
  }
211
- // install-module-linked itself is small, but a target native package can be large (@duckdb/node-
212
- // api's ~110MB is the current instance): deferred the same way embed/static.ts defers
213
- // @huggingface/tokenizers, so requiring it stays inside the already-gated branch below rather
214
- // than running for every store/index.ts load.
211
+ // install-module-linked is small, but a target native package can be large (@duckdb/node-api's
212
+ // ~110MB), so it is required lazily inside the gated branch below, not for every store/index.ts load.
215
213
  var _require = typeof require === 'undefined' ? _nodemodule.default.createRequire(require("url").pathToFileURL(__filename).toString()) : require;
216
214
  var _dirname = (0, _nodepath.dirname)(typeof __filename !== 'undefined' ? __filename : (0, _nodeurl.fileURLToPath)(require("url").pathToFileURL(__filename).toString()));
217
215
  function packageNodeModules() {
@@ -228,12 +226,8 @@ function packageNodeModules() {
228
226
  }
229
227
  }
230
228
  var installing = new Map();
231
- // De-dupes concurrent installs within this process (see spawn-term's loadInk for the shape).
232
- // The install here is async -- the load site already awaits a dynamic import -- so a bare
233
- // attempted flag (xz-compat's `installationAttempted`, enough for its synchronous single-target
234
- // install) isn't enough on its own; concurrent callers instead await the same in-flight promise,
235
- // keyed by specifier and target so tests exercising several installs in one process don't share
236
- // one slot. A failed install is not cached, so a later call retries.
229
+ // De-dupes concurrent installs: since the install is async, concurrent callers await the same
230
+ // in-flight promise, keyed by specifier and target. A failed install is not cached, so a later call retries.
237
231
  function installOnce(specifier, nodeModulesPath) {
238
232
  var key = "".concat(specifier, "\n").concat(nodeModulesPath);
239
233
  var promise = installing.get(key);
@@ -247,12 +241,8 @@ function installOnce(specifier, nodeModulesPath) {
247
241
  }
248
242
  return promise;
249
243
  }
250
- // Node caches a bare specifier's package resolution -- including a "not found" miss -- for the
251
- // life of the process, so retrying `import(importName)` right after installing sees the same
252
- // stale miss and falls through to a bogus index.js guess instead of the package's real entry
253
- // (verified against a real global install: the plain-specifier retry failed there, this did
254
- // not). Reading the freshly-installed package's own package.json and importing its entry file
255
- // by an absolute file: URL sidesteps that stale cache instead of re-resolving the bare name.
244
+ // Node caches a bare specifier's resolution, including a "not found" miss, for the process
245
+ // lifetime; importing the entry by an absolute file: URL instead of the bare name sidesteps that.
256
246
  function resolveEntryUrl(importName, nodeModulesPath) {
257
247
  var _pkg_main;
258
248
  var pkgDir = _nodepath.join.apply(void 0, [
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/native.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport Module from 'node:module';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\nimport { SenseError } from '../errors.ts';\n\n// A store's optional native package, and the strings its error messages and install notice name.\nexport interface NativeDescriptor {\n store: string;\n pkg: string;\n sizeHint: string;\n}\n\n// install-module-linked itself is small, but a target native package can be large (@duckdb/node-\n// api's ~110MB is the current instance): deferred the same way embed/static.ts defers\n// @huggingface/tokenizers, so requiring it stays inside the already-gated branch below rather\n// than running for every store/index.ts load.\nconst _require = typeof require === 'undefined' ? Module.createRequire(import.meta.url) : require;\nconst _dirname = dirname(typeof __filename !== 'undefined' ? __filename : fileURLToPath(import.meta.url));\n\n// Walks up from this file's own directory to find the real package.json, rather than a fixed\n// dot-count from __dirname (xz-compat's `../../node_modules`): this file sits at a different\n// depth under src/ during `tsds test:node` than under the built dist/{cjs,esm}/store output, so a\n// hardcoded depth is right for one and wrong for the other. Works the same way for a\n// globally-installed `sense`, whose node_modules this resolves to -- never the caller's cwd.\nexport function packageNodeModules(): string {\n let dir = _dirname;\n for (;;) {\n const candidate = join(dir, 'package.json');\n if (existsSync(candidate)) {\n const pkg = JSON.parse(readFileSync(candidate, 'utf8')) as { name?: string };\n if (pkg.name === 'sensemaking') return join(dir, 'node_modules');\n }\n const parent = dirname(dir);\n if (parent === dir) throw new Error('could not locate the sensemaking package root to install a native dependency into');\n dir = parent;\n }\n}\n\nconst installing = new Map<string, Promise<void>>();\n\n// De-dupes concurrent installs within this process (see spawn-term's loadInk for the shape).\n// The install here is async -- the load site already awaits a dynamic import -- so a bare\n// attempted flag (xz-compat's `installationAttempted`, enough for its synchronous single-target\n// install) isn't enough on its own; concurrent callers instead await the same in-flight promise,\n// keyed by specifier and target so tests exercising several installs in one process don't share\n// one slot. A failed install is not cached, so a later call retries.\nfunction installOnce(specifier: string, nodeModulesPath: string): Promise<void> {\n const key = `${specifier}\\n${nodeModulesPath}`;\n let promise = installing.get(key);\n if (!promise) {\n const installModuleLinked = (_require('install-module-linked') as { default: (specifier: string, nodeModulesPath: string) => Promise<string> }).default;\n promise = installModuleLinked(specifier, nodeModulesPath).then(\n () => {},\n (err) => {\n installing.delete(key);\n throw err;\n }\n );\n installing.set(key, promise);\n }\n return promise;\n}\n\n// Node caches a bare specifier's package resolution -- including a \"not found\" miss -- for the\n// life of the process, so retrying `import(importName)` right after installing sees the same\n// stale miss and falls through to a bogus index.js guess instead of the package's real entry\n// (verified against a real global install: the plain-specifier retry failed there, this did\n// not). Reading the freshly-installed package's own package.json and importing its entry file\n// by an absolute file: URL sidesteps that stale cache instead of re-resolving the bare name.\nfunction resolveEntryUrl(importName: string, nodeModulesPath: string): string {\n const pkgDir = join(nodeModulesPath, ...importName.split('/'));\n const pkg = JSON.parse(readFileSync(join(pkgDir, 'package.json'), 'utf8')) as { main?: string; exports?: string };\n const entry = typeof pkg.exports === 'string' ? pkg.exports : (pkg.main ?? 'index.js');\n return pathToFileURL(join(pkgDir, entry)).href;\n}\n\n// Import-then-install-then-retry, over an injectable importName so the failure path (import AND\n// install both fail) can be exercised for real in tests without downloading a real store's native\n// binding. importName defaults to descriptor.pkg, which is what production always wants; the\n// thrown errors name descriptor.pkg regardless, since that is what a real user needs to install.\nexport async function loadOrInstall<T>(descriptor: NativeDescriptor, nodeModulesPath: string, importName: string = descriptor.pkg): Promise<T> {\n try {\n return (await import(importName)) as T;\n } catch {\n console.error(`sense: store \"${descriptor.store}\" needs ${descriptor.pkg}; installing it now (one-time download, ${descriptor.sizeHint})...`);\n try {\n await installOnce(importName, nodeModulesPath);\n } catch (installErr) {\n throw new SenseError(\n 'STORE_DEPENDENCY_MISSING',\n `store \"${descriptor.store}\" needs ${descriptor.pkg}, and installing it automatically failed (${(installErr as Error).message}); this can happen offline, in a sandboxed environment, or when node_modules is read-only or owned by another user (e.g. under a global install) -- run \\`npm install ${descriptor.pkg}\\` yourself and try again`\n );\n }\n try {\n return (await import(resolveEntryUrl(importName, nodeModulesPath))) as T;\n } catch (loadErr) {\n throw new SenseError(\n 'STORE_DEPENDENCY_MISSING',\n `store \"${descriptor.store}\" installed ${descriptor.pkg} but it could not be loaded (${(loadErr as Error).message}); it may not be available for this platform (${process.platform}-${process.arch}) -- run \\`npm install ${descriptor.pkg}\\` to see the underlying error`\n );\n }\n }\n}\n"],"names":["loadOrInstall","packageNodeModules","_require","require","Module","createRequire","_dirname","dirname","__filename","fileURLToPath","dir","candidate","join","existsSync","pkg","JSON","parse","readFileSync","name","parent","Error","installing","Map","installOnce","specifier","nodeModulesPath","key","promise","get","installModuleLinked","default","then","err","delete","set","resolveEntryUrl","importName","pkgDir","split","entry","exports","main","pathToFileURL","href","descriptor","installErr","loadErr","console","error","store","sizeHint","SenseError","message","process","platform","arch"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/native.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport Module from 'node:module';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\nimport { SenseError } from '../errors.ts';\n\n// A store's optional native package, and the strings its error messages and install notice name.\nexport interface NativeDescriptor {\n store: string;\n pkg: string;\n sizeHint: string;\n}\n\n// install-module-linked is small, but a target native package can be large (@duckdb/node-api's\n// ~110MB), so it is required lazily inside the gated branch below, not for every store/index.ts load.\nconst _require = typeof require === 'undefined' ? Module.createRequire(import.meta.url) : require;\nconst _dirname = dirname(typeof __filename !== 'undefined' ? __filename : fileURLToPath(import.meta.url));\n\n// Walks up from this file's own directory rather than a fixed dot-count: it sits at a\n// different depth under src/ than under built dist/{cjs,esm}/store output.\nexport function packageNodeModules(): string {\n let dir = _dirname;\n for (;;) {\n const candidate = join(dir, 'package.json');\n if (existsSync(candidate)) {\n const pkg = JSON.parse(readFileSync(candidate, 'utf8')) as { name?: string };\n if (pkg.name === 'sensemaking') return join(dir, 'node_modules');\n }\n const parent = dirname(dir);\n if (parent === dir) throw new Error('could not locate the sensemaking package root to install a native dependency into');\n dir = parent;\n }\n}\n\nconst installing = new Map<string, Promise<void>>();\n\n// De-dupes concurrent installs: since the install is async, concurrent callers await the same\n// in-flight promise, keyed by specifier and target. A failed install is not cached, so a later call retries.\nfunction installOnce(specifier: string, nodeModulesPath: string): Promise<void> {\n const key = `${specifier}\\n${nodeModulesPath}`;\n let promise = installing.get(key);\n if (!promise) {\n const installModuleLinked = (_require('install-module-linked') as { default: (specifier: string, nodeModulesPath: string) => Promise<string> }).default;\n promise = installModuleLinked(specifier, nodeModulesPath).then(\n () => {},\n (err) => {\n installing.delete(key);\n throw err;\n }\n );\n installing.set(key, promise);\n }\n return promise;\n}\n\n// Node caches a bare specifier's resolution, including a \"not found\" miss, for the process\n// lifetime; importing the entry by an absolute file: URL instead of the bare name sidesteps that.\nfunction resolveEntryUrl(importName: string, nodeModulesPath: string): string {\n const pkgDir = join(nodeModulesPath, ...importName.split('/'));\n const pkg = JSON.parse(readFileSync(join(pkgDir, 'package.json'), 'utf8')) as { main?: string; exports?: string };\n const entry = typeof pkg.exports === 'string' ? pkg.exports : (pkg.main ?? 'index.js');\n return pathToFileURL(join(pkgDir, entry)).href;\n}\n\n// Import-then-install-then-retry, over an injectable importName so the failure path can be\n// exercised in tests without a real native binding. Thrown errors always name descriptor.pkg.\nexport async function loadOrInstall<T>(descriptor: NativeDescriptor, nodeModulesPath: string, importName: string = descriptor.pkg): Promise<T> {\n try {\n return (await import(importName)) as T;\n } catch {\n console.error(`sense: store \"${descriptor.store}\" needs ${descriptor.pkg}; installing it now (one-time download, ${descriptor.sizeHint})...`);\n try {\n await installOnce(importName, nodeModulesPath);\n } catch (installErr) {\n throw new SenseError(\n 'STORE_DEPENDENCY_MISSING',\n `store \"${descriptor.store}\" needs ${descriptor.pkg}, and installing it automatically failed (${(installErr as Error).message}); this can happen offline, in a sandboxed environment, or when node_modules is read-only or owned by another user (e.g. under a global install) -- run \\`npm install ${descriptor.pkg}\\` yourself and try again`\n );\n }\n try {\n return (await import(resolveEntryUrl(importName, nodeModulesPath))) as T;\n } catch (loadErr) {\n throw new SenseError(\n 'STORE_DEPENDENCY_MISSING',\n `store \"${descriptor.store}\" installed ${descriptor.pkg} but it could not be loaded (${(loadErr as Error).message}); it may not be available for this platform (${process.platform}-${process.arch}) -- run \\`npm install ${descriptor.pkg}\\` to see the underlying error`\n );\n }\n }\n}\n"],"names":["loadOrInstall","packageNodeModules","_require","require","Module","createRequire","_dirname","dirname","__filename","fileURLToPath","dir","candidate","join","existsSync","pkg","JSON","parse","readFileSync","name","parent","Error","installing","Map","installOnce","specifier","nodeModulesPath","key","promise","get","installModuleLinked","default","then","err","delete","set","resolveEntryUrl","importName","pkgDir","split","entry","exports","main","pathToFileURL","href","descriptor","installErr","loadErr","console","error","store","sizeHint","SenseError","message","process","platform","arch"],"mappings":";;;;;;;;;;;QAkEsBA;eAAAA;;QA9CNC;eAAAA;;;sBApByB;iEACtB;wBACW;uBACe;wBAClB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAS3B,+FAA+F;AAC/F,sGAAsG;AACtG,IAAMC,WAAW,OAAOC,YAAY,cAAcC,mBAAM,CAACC,aAAa,CAAC,uDAAmBF;AAC1F,IAAMG,WAAWC,IAAAA,iBAAO,EAAC,OAAOC,eAAe,cAAcA,aAAaC,IAAAA,sBAAa,EAAC;AAIjF,SAASR;IACd,IAAIS,MAAMJ;IACV,OAAS;QACP,IAAMK,YAAYC,IAAAA,cAAI,EAACF,KAAK;QAC5B,IAAIG,IAAAA,kBAAU,EAACF,YAAY;YACzB,IAAMG,MAAMC,KAAKC,KAAK,CAACC,IAAAA,oBAAY,EAACN,WAAW;YAC/C,IAAIG,IAAII,IAAI,KAAK,eAAe,OAAON,IAAAA,cAAI,EAACF,KAAK;QACnD;QACA,IAAMS,SAASZ,IAAAA,iBAAO,EAACG;QACvB,IAAIS,WAAWT,KAAK,MAAM,IAAIU,MAAM;QACpCV,MAAMS;IACR;AACF;AAEA,IAAME,aAAa,IAAIC;AAEvB,8FAA8F;AAC9F,6GAA6G;AAC7G,SAASC,YAAYC,SAAiB,EAAEC,eAAuB;IAC7D,IAAMC,MAAM,AAAC,GAAgBD,OAAdD,WAAU,MAAoB,OAAhBC;IAC7B,IAAIE,UAAUN,WAAWO,GAAG,CAACF;IAC7B,IAAI,CAACC,SAAS;QACZ,IAAME,sBAAsB,AAAC3B,SAAS,yBAA0G4B,OAAO;QACvJH,UAAUE,oBAAoBL,WAAWC,iBAAiBM,IAAI,CAC5D,YAAO,GACP,SAACC;YACCX,WAAWY,MAAM,CAACP;YAClB,MAAMM;QACR;QAEFX,WAAWa,GAAG,CAACR,KAAKC;IACtB;IACA,OAAOA;AACT;AAEA,2FAA2F;AAC3F,kGAAkG;AAClG,SAASQ,gBAAgBC,UAAkB,EAAEX,eAAuB;QAGHX;IAF/D,IAAMuB,SAASzB,cAAI,OAAJA,KAAAA,GAAAA;QAAKa;KAA0C,CAA/Cb,OAAsB,qBAAGwB,WAAWE,KAAK,CAAC;IACzD,IAAMxB,MAAMC,KAAKC,KAAK,CAACC,IAAAA,oBAAY,EAACL,IAAAA,cAAI,EAACyB,QAAQ,iBAAiB;IAClE,IAAME,QAAQ,OAAOzB,IAAI0B,OAAO,KAAK,WAAW1B,IAAI0B,OAAO,IAAI1B,YAAAA,IAAI2B,IAAI,cAAR3B,uBAAAA,YAAY;IAC3E,OAAO4B,IAAAA,sBAAa,EAAC9B,IAAAA,cAAI,EAACyB,QAAQE,QAAQI,IAAI;AAChD;AAIO,SAAe3C;wCAAiB4C,UAA4B,EAAEnB,eAAuB;YAAEW,oBAOjFS,YAQAC;;;;;oBAfiFV,aAAAA,oEAAqBQ,WAAW9B,GAAG;;;;;;;;;oBAErH;;wBAAM,gBAAOsB;2EAAP;;;;oBAAd;;wBAAQ;;;;oBAERW,QAAQC,KAAK,CAAC,AAAC,iBAA2CJ,OAA3BA,WAAWK,KAAK,EAAC,YAAmEL,OAAzDA,WAAW9B,GAAG,EAAC,4CAA8D,OAApB8B,WAAWM,QAAQ,EAAC;;;;;;;;;oBAErI;;wBAAM3B,YAAYa,YAAYX;;;oBAA9B;;;;;;oBACOoB;oBACP,MAAM,IAAIM,oBAAU,CAClB,4BACA,AAAC,UAAoCP,OAA3BA,WAAWK,KAAK,EAAC,YAAqE,OAA3DL,WAAW9B,GAAG,EAAC,8CAAkP8B,OAAtM,AAACC,WAAqBO,OAAO,EAAC,yKAAuL,OAAfR,WAAW9B,GAAG,EAAC;;;;;;;;oBAI/S;;wBAAM,gBAAOqB,gBAAgBC,YAAYX;2EAAnC;;;;oBAAd;;wBAAQ;;;oBACDqB;oBACP,MAAM,IAAIK,oBAAU,CAClB,4BACA,AAAC,UAAwCP,OAA/BA,WAAWK,KAAK,EAAC,gBAA4D,OAA9CL,WAAW9B,GAAG,EAAC,iCAA0GuC,OAA3E,AAACP,QAAkBM,OAAO,EAAC,kDAAoEC,OAApBA,QAAQC,QAAQ,EAAC,KAAyCV,OAAtCS,QAAQE,IAAI,EAAC,0BAAwC,OAAfX,WAAW9B,GAAG,EAAC;;;;;;;;;;;;IAInP"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/sql-functions.ts"],"sourcesContent":["import posix from 'node:path/posix';\n\n// has(field, value) / basename(path, suffix): the two sense-supplied SQL functions with no\n// engine-specific pieces, shared by sqlite/sql-functions.ts and duckdb/sql-functions.ts so each\n// store registers the identical implementation instead of a hand-copied one (DRY).\n\n// JSON-array field -> membership, string field -> substring, NULL -> false.\nexport function hasImpl(field: unknown, value: unknown): number {\n if (field === null || field === undefined) return 0;\n const needle = String(value);\n if (typeof field === 'string') {\n if (field.startsWith('[')) {\n try {\n const parsed = JSON.parse(field);\n if (Array.isArray(parsed)) return parsed.some((item) => String(item) === needle) ? 1 : 0;\n } catch {}\n }\n return field.includes(needle) ? 1 : 0;\n }\n return String(field).includes(needle) ? 1 : 0;\n}\n\n// Unix basename(path, suffix?): the filename, minus suffix when it ends with one. Neither\n// engine has a filename function of its own, and LIKE tricks that fake one also match folder\n// names.\nexport function basenameImpl(path: unknown, suffix?: unknown): string | null {\n if (path === null || path === undefined) return null;\n const name = posix.basename(String(path));\n const tail = suffix === null || suffix === undefined ? '' : String(suffix);\n // POSIX: a suffix identical to the whole name is not removed (node's own basename strips it).\n return tail !== '' && tail !== name && name.endsWith(tail) ? name.slice(0, -tail.length) : name;\n}\n"],"names":["basenameImpl","hasImpl","field","value","undefined","needle","String","startsWith","parsed","JSON","parse","Array","isArray","some","item","includes","path","suffix","name","posix","basename","tail","endsWith","slice","length"],"mappings":";;;;;;;;;;;QAyBgBA;eAAAA;;QAlBAC;eAAAA;;;4DAPE;;;;;;AAOX,SAASA,QAAQC,KAAc,EAAEC,KAAc;IACpD,IAAID,UAAU,QAAQA,UAAUE,WAAW,OAAO;IAClD,IAAMC,SAASC,OAAOH;IACtB,IAAI,OAAOD,UAAU,UAAU;QAC7B,IAAIA,MAAMK,UAAU,CAAC,MAAM;YACzB,IAAI;gBACF,IAAMC,SAASC,KAAKC,KAAK,CAACR;gBAC1B,IAAIS,MAAMC,OAAO,CAACJ,SAAS,OAAOA,OAAOK,IAAI,CAAC,SAACC;2BAASR,OAAOQ,UAAUT;qBAAU,IAAI;YACzF,EAAE,eAAM,CAAC;QACX;QACA,OAAOH,MAAMa,QAAQ,CAACV,UAAU,IAAI;IACtC;IACA,OAAOC,OAAOJ,OAAOa,QAAQ,CAACV,UAAU,IAAI;AAC9C;AAKO,SAASL,aAAagB,IAAa,EAAEC,MAAgB;IAC1D,IAAID,SAAS,QAAQA,SAASZ,WAAW,OAAO;IAChD,IAAMc,OAAOC,cAAK,CAACC,QAAQ,CAACd,OAAOU;IACnC,IAAMK,OAAOJ,WAAW,QAAQA,WAAWb,YAAY,KAAKE,OAAOW;IACnE,8FAA8F;IAC9F,OAAOI,SAAS,MAAMA,SAASH,QAAQA,KAAKI,QAAQ,CAACD,QAAQH,KAAKK,KAAK,CAAC,GAAG,CAACF,KAAKG,MAAM,IAAIN;AAC7F"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/sql-functions.ts"],"sourcesContent":["import posix from 'node:path/posix';\n\n// has(field, value) / basename(path, suffix): the two sense-supplied SQL functions with no\n// engine-specific pieces, registered identically by each store instead of a hand-copied one.\n\n// JSON-array field -> membership, string field -> substring, NULL -> false.\nexport function hasImpl(field: unknown, value: unknown): number {\n if (field === null || field === undefined) return 0;\n const needle = String(value);\n if (typeof field === 'string') {\n if (field.startsWith('[')) {\n try {\n const parsed = JSON.parse(field);\n if (Array.isArray(parsed)) return parsed.some((item) => String(item) === needle) ? 1 : 0;\n } catch {}\n }\n return field.includes(needle) ? 1 : 0;\n }\n return String(field).includes(needle) ? 1 : 0;\n}\n\n// Unix basename(path, suffix?): the filename, minus suffix when it ends with one. Neither engine\n// has a filename function of its own, and LIKE tricks that fake one also match folder names.\nexport function basenameImpl(path: unknown, suffix?: unknown): string | null {\n if (path === null || path === undefined) return null;\n const name = posix.basename(String(path));\n const tail = suffix === null || suffix === undefined ? '' : String(suffix);\n // POSIX: a suffix identical to the whole name is not removed (node's own basename strips it).\n return tail !== '' && tail !== name && name.endsWith(tail) ? name.slice(0, -tail.length) : name;\n}\n"],"names":["basenameImpl","hasImpl","field","value","undefined","needle","String","startsWith","parsed","JSON","parse","Array","isArray","some","item","includes","path","suffix","name","posix","basename","tail","endsWith","slice","length"],"mappings":";;;;;;;;;;;QAuBgBA;eAAAA;;QAjBAC;eAAAA;;;4DANE;;;;;;AAMX,SAASA,QAAQC,KAAc,EAAEC,KAAc;IACpD,IAAID,UAAU,QAAQA,UAAUE,WAAW,OAAO;IAClD,IAAMC,SAASC,OAAOH;IACtB,IAAI,OAAOD,UAAU,UAAU;QAC7B,IAAIA,MAAMK,UAAU,CAAC,MAAM;YACzB,IAAI;gBACF,IAAMC,SAASC,KAAKC,KAAK,CAACR;gBAC1B,IAAIS,MAAMC,OAAO,CAACJ,SAAS,OAAOA,OAAOK,IAAI,CAAC,SAACC;2BAASR,OAAOQ,UAAUT;qBAAU,IAAI;YACzF,EAAE,eAAM,CAAC;QACX;QACA,OAAOH,MAAMa,QAAQ,CAACV,UAAU,IAAI;IACtC;IACA,OAAOC,OAAOJ,OAAOa,QAAQ,CAACV,UAAU,IAAI;AAC9C;AAIO,SAASL,aAAagB,IAAa,EAAEC,MAAgB;IAC1D,IAAID,SAAS,QAAQA,SAASZ,WAAW,OAAO;IAChD,IAAMc,OAAOC,cAAK,CAACC,QAAQ,CAACd,OAAOU;IACnC,IAAMK,OAAOJ,WAAW,QAAQA,WAAWb,YAAY,KAAKE,OAAOW;IACnE,8FAA8F;IAC9F,OAAOI,SAAS,MAAMA,SAASH,QAAQA,KAAKI,QAAQ,CAACD,QAAQH,KAAKK,KAAK,CAAC,GAAG,CAACF,KAAKG,MAAM,IAAIN;AAC7F"}
@@ -350,10 +350,8 @@ function _wrap_async_generator(fn) {
350
350
  return new _async_generator(fn.apply(this, arguments));
351
351
  };
352
352
  }
353
- // Wraps node:sqlite's synchronous DatabaseSync in the async Connection/Statement shape every
354
- // store presents. Every method below does its real work synchronously and returns an already-
355
- // resolved promise, so reconcile's loop, the feature hooks, and runBatch never actually cross
356
- // an async boundary internally -- no regression against the pre-Store synchronous code.
353
+ // Wraps node:sqlite's synchronous DatabaseSync in the async Connection/Statement shape every store presents. Every method does its real
354
+ // work synchronously and returns an already-resolved promise, so reconcile's loop, the feature hooks, and runBatch never cross an async boundary internally.
357
355
  var SqliteStatement = /*#__PURE__*/ function() {
358
356
  "use strict";
359
357
  function SqliteStatement(stmt) {
@@ -455,10 +453,8 @@ function createConnection(db) {
455
453
  });
456
454
  })();
457
455
  },
458
- runBatch: // Prepares once and loops synchronously: today's code, unchanged, wrapped as one async call
459
- // so features share one Connection contract with DuckDB. Joins the caller's transaction when
460
- // there is one (reconcile); otherwise opens its own, so a standalone batch (a vector write
461
- // outside any Store.transaction()) stays atomic and commits once, not once per row.
456
+ runBatch: // Prepares once and loops synchronously, wrapped as one async call so features share one
457
+ // Connection contract with DuckDB. Joins the caller's transaction when there is one (reconcile); otherwise opens its own, so a standalone batch stays atomic and commits once, not per row.
462
458
  function runBatch(sql, paramRows) {
463
459
  return _async_to_generator(function() {
464
460
  return _ts_generator(this, function(_state) {
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/sqlite/connection.ts"],"sourcesContent":["import type { DatabaseSync, StatementSync } from 'node:sqlite';\nimport { withTransaction } from '../transaction.ts';\nimport type { Connection, RunResult, Statement } from '../types.ts';\n\n// Wraps node:sqlite's synchronous DatabaseSync in the async Connection/Statement shape every\n// store presents. Every method below does its real work synchronously and returns an already-\n// resolved promise, so reconcile's loop, the feature hooks, and runBatch never actually cross\n// an async boundary internally -- no regression against the pre-Store synchronous code.\nclass SqliteStatement implements Statement {\n private stmt: StatementSync;\n\n constructor(stmt: StatementSync) {\n this.stmt = stmt;\n }\n\n async run(...params: unknown[]): Promise<RunResult> {\n return this.stmt.run(...(params as Parameters<StatementSync['run']>));\n }\n\n async get(...params: unknown[]): Promise<unknown> {\n return this.stmt.get(...(params as Parameters<StatementSync['get']>));\n }\n\n async all(...params: unknown[]): Promise<unknown[]> {\n return this.stmt.all(...(params as Parameters<StatementSync['all']>));\n }\n\n async *iterate(...params: unknown[]): AsyncIterable<unknown> {\n yield* this.stmt.iterate(...(params as Parameters<StatementSync['iterate']>));\n }\n\n columns(): Array<{ name: string }> {\n return this.stmt.columns();\n }\n\n setReadBigInts(enabled: boolean): void {\n this.stmt.setReadBigInts(enabled);\n }\n}\n\nexport function createConnection(db: DatabaseSync): Connection {\n const conn: Connection = {\n async exec(sql: string): Promise<void> {\n db.exec(sql);\n },\n async prepare(sql: string): Promise<Statement> {\n return new SqliteStatement(db.prepare(sql));\n },\n // Prepares once and loops synchronously: today's code, unchanged, wrapped as one async call\n // so features share one Connection contract with DuckDB. Joins the caller's transaction when\n // there is one (reconcile); otherwise opens its own, so a standalone batch (a vector write\n // outside any Store.transaction()) stays atomic and commits once, not once per row.\n async runBatch(sql: string, paramRows: unknown[][]): Promise<void> {\n if (paramRows.length === 0) return;\n await withTransaction(conn, async () => {\n const stmt = db.prepare(sql);\n for (const row of paramRows) stmt.run(...(row as Parameters<StatementSync['run']>));\n });\n },\n };\n return conn;\n}\n"],"names":["createConnection","SqliteStatement","stmt","run","params","get","all","iterate","columns","setReadBigInts","enabled","db","conn","exec","sql","prepare","runBatch","paramRows","length","withTransaction","row"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/sqlite/connection.ts"],"sourcesContent":["import type { DatabaseSync, StatementSync } from 'node:sqlite';\nimport { withTransaction } from '../transaction.ts';\nimport type { Connection, RunResult, Statement } from '../types.ts';\n\n// Wraps node:sqlite's synchronous DatabaseSync in the async Connection/Statement shape every store presents. Every method does its real\n// work synchronously and returns an already-resolved promise, so reconcile's loop, the feature hooks, and runBatch never cross an async boundary internally.\nclass SqliteStatement implements Statement {\n private stmt: StatementSync;\n\n constructor(stmt: StatementSync) {\n this.stmt = stmt;\n }\n\n async run(...params: unknown[]): Promise<RunResult> {\n return this.stmt.run(...(params as Parameters<StatementSync['run']>));\n }\n\n async get(...params: unknown[]): Promise<unknown> {\n return this.stmt.get(...(params as Parameters<StatementSync['get']>));\n }\n\n async all(...params: unknown[]): Promise<unknown[]> {\n return this.stmt.all(...(params as Parameters<StatementSync['all']>));\n }\n\n async *iterate(...params: unknown[]): AsyncIterable<unknown> {\n yield* this.stmt.iterate(...(params as Parameters<StatementSync['iterate']>));\n }\n\n columns(): Array<{ name: string }> {\n return this.stmt.columns();\n }\n\n setReadBigInts(enabled: boolean): void {\n this.stmt.setReadBigInts(enabled);\n }\n}\n\nexport function createConnection(db: DatabaseSync): Connection {\n const conn: Connection = {\n async exec(sql: string): Promise<void> {\n db.exec(sql);\n },\n async prepare(sql: string): Promise<Statement> {\n return new SqliteStatement(db.prepare(sql));\n },\n // Prepares once and loops synchronously, wrapped as one async call so features share one\n // Connection contract with DuckDB. Joins the caller's transaction when there is one (reconcile); otherwise opens its own, so a standalone batch stays atomic and commits once, not per row.\n async runBatch(sql: string, paramRows: unknown[][]): Promise<void> {\n if (paramRows.length === 0) return;\n await withTransaction(conn, async () => {\n const stmt = db.prepare(sql);\n for (const row of paramRows) stmt.run(...(row as Parameters<StatementSync['run']>));\n });\n },\n };\n return conn;\n}\n"],"names":["createConnection","SqliteStatement","stmt","run","params","get","all","iterate","columns","setReadBigInts","enabled","db","conn","exec","sql","prepare","runBatch","paramRows","length","withTransaction","row"],"mappings":"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"}